diff --git a/.changeset/afraid-houses-learn.md b/.changeset/afraid-houses-learn.md
deleted file mode 100644
index 3d161965bae..00000000000
--- a/.changeset/afraid-houses-learn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#updated use real contracts in ccipreader_tests where possible
diff --git a/.changeset/beige-geckos-explode.md b/.changeset/beige-geckos-explode.md
deleted file mode 100644
index 9f06a9c989b..00000000000
--- a/.changeset/beige-geckos-explode.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated Gracefully fail if CL_DATABASE_URL is not set.
diff --git a/.changeset/big-camels-report.md b/.changeset/big-camels-report.md
deleted file mode 100644
index f81f66b9138..00000000000
--- a/.changeset/big-camels-report.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#bugfix fix non-idempotent loopp registry.Register
diff --git a/.changeset/brave-cooks-itch.md b/.changeset/brave-cooks-itch.md
deleted file mode 100644
index 1ed3dd7e117..00000000000
--- a/.changeset/brave-cooks-itch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated feat(job-distributor): support tron chain type on sync
diff --git a/.changeset/breezy-kings-clean.md b/.changeset/breezy-kings-clean.md
deleted file mode 100644
index b72a0689019..00000000000
--- a/.changeset/breezy-kings-clean.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Potential bug introduced from chain selector refactor, not causing issue now since only EVM is used, but need to fix #bugfix
diff --git a/.changeset/bright-keys-whisper.md b/.changeset/bright-keys-whisper.md
deleted file mode 100644
index 16bf56b2ac9..00000000000
--- a/.changeset/bright-keys-whisper.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-allow different decimals on different chains for token pools
diff --git a/.changeset/chilled-papayas-swim.md b/.changeset/chilled-papayas-swim.md
deleted file mode 100644
index e2f2b536514..00000000000
--- a/.changeset/chilled-papayas-swim.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#removed Remove duplicated testing util for p2p_key only.
diff --git a/.changeset/chilled-suits-do.md b/.changeset/chilled-suits-do.md
deleted file mode 100644
index 611fe95d159..00000000000
--- a/.changeset/chilled-suits-do.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Updated the Solana TXM compute unit limit estimation feature to use the max 1.4M compute unit limit for simulation and enable SigVerify #updated
diff --git a/.changeset/chilly-stingrays-press.md b/.changeset/chilly-stingrays-press.md
deleted file mode 100644
index 1fe2e80f2b0..00000000000
--- a/.changeset/chilly-stingrays-press.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Removing ccip-tests/\* dependencies and moving ccip tests under a directory in smoke
diff --git a/.changeset/clean-files-beg.md b/.changeset/clean-files-beg.md
deleted file mode 100644
index 1357a044cb0..00000000000
--- a/.changeset/clean-files-beg.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Adding OCR3 promwrapper to LLO #internal
diff --git a/.changeset/clever-knives-tap.md b/.changeset/clever-knives-tap.md
deleted file mode 100644
index 8683e89f77d..00000000000
--- a/.changeset/clever-knives-tap.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added Sei config and error mapping
diff --git a/.changeset/cold-coats-battle.md b/.changeset/cold-coats-battle.md
deleted file mode 100644
index 1a72d025bde..00000000000
--- a/.changeset/cold-coats-battle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal minor rename of various gethwrappers
diff --git a/.changeset/cold-pillows-sleep.md b/.changeset/cold-pillows-sleep.md
deleted file mode 100644
index 45e4e999111..00000000000
--- a/.changeset/cold-pillows-sleep.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Extract EVM MultiNode to chainlink-framework. #internal
diff --git a/.changeset/cool-penguins-raise.md b/.changeset/cool-penguins-raise.md
deleted file mode 100644
index c47839be310..00000000000
--- a/.changeset/cool-penguins-raise.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated Remove custom ed25519 private to public key conversion.
diff --git a/.changeset/cuddly-turtles-arrive.md b/.changeset/cuddly-turtles-arrive.md
deleted file mode 100644
index 81ceed3e8ff..00000000000
--- a/.changeset/cuddly-turtles-arrive.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal adding solana devnet to ccip deployment
diff --git a/.changeset/cyan-ladybugs-check.md b/.changeset/cyan-ladybugs-check.md
deleted file mode 100644
index d430890001a..00000000000
--- a/.changeset/cyan-ladybugs-check.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-validates response from gateway in workflow/fetcher
diff --git a/.changeset/dull-readers-rush.md b/.changeset/dull-readers-rush.md
deleted file mode 100644
index 3b6f2ae8758..00000000000
--- a/.changeset/dull-readers-rush.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Reporting number of OCR3 instances running using promwrapper #internal
diff --git a/.changeset/eight-meals-march.md b/.changeset/eight-meals-march.md
deleted file mode 100644
index f2439280063..00000000000
--- a/.changeset/eight-meals-march.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-"chainlink": patch
----
-
-Prevents a panic in test helper for confirming transaction
-and adds encrypted public key to a peer before calling addNodes
-on CapabilitiesRegistry
diff --git a/.changeset/eight-tigers-march.md b/.changeset/eight-tigers-march.md
deleted file mode 100644
index 611628f2ef6..00000000000
--- a/.changeset/eight-tigers-march.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added Adding 5 chains (B^2, BoB, Berachain, Unichain, Worldchain configs)
diff --git a/.changeset/eighty-geckos-switch.md b/.changeset/eighty-geckos-switch.md
deleted file mode 100644
index b67dfb0ec79..00000000000
--- a/.changeset/eighty-geckos-switch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Reduce PriceMin on Avalanche to 1 gwei #nops
diff --git a/.changeset/eleven-cheetahs-care.md b/.changeset/eleven-cheetahs-care.md
deleted file mode 100644
index 2ac6417b342..00000000000
--- a/.changeset/eleven-cheetahs-care.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-"chainlink": patch
----
-
-Add panic recovery to wsrpc mercury client
-
-- Should help to make nodes running wsrpc v0.8.2 more stable #bugfix
diff --git a/.changeset/five-beds-wait.md b/.changeset/five-beds-wait.md
deleted file mode 100644
index 36ee14f49b6..00000000000
--- a/.changeset/five-beds-wait.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#bugfix Add chaintype.ChainZircuit to chaintypes with rollup support in L1 oracle to prevent a nil L1 oracle being used for Zircuit's gas estimator
diff --git a/.changeset/five-gifts-end.md b/.changeset/five-gifts-end.md
deleted file mode 100644
index dd13fda476d..00000000000
--- a/.changeset/five-gifts-end.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added stream job delete capability
diff --git a/.changeset/fluffy-lizards-laugh.md b/.changeset/fluffy-lizards-laugh.md
deleted file mode 100644
index 3d38170c2d8..00000000000
--- a/.changeset/fluffy-lizards-laugh.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Changed RMNRemote and RMNHome parameter f to fObserve and fSign #updated
diff --git a/.changeset/forty-foxes-rescue.md b/.changeset/forty-foxes-rescue.md
deleted file mode 100644
index 9456ebe5e36..00000000000
--- a/.changeset/forty-foxes-rescue.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#removed Remove unused ocr1 key files.
diff --git a/.changeset/fresh-lobsters-fly.md b/.changeset/fresh-lobsters-fly.md
deleted file mode 100644
index 12b9c317dcb..00000000000
--- a/.changeset/fresh-lobsters-fly.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#internal Refactored ChainComponents tests to run in parallel
diff --git a/.changeset/friendly-tigers-argue.md b/.changeset/friendly-tigers-argue.md
deleted file mode 100644
index 25aff7e13ae..00000000000
--- a/.changeset/friendly-tigers-argue.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal change gethwrapper to allow for foundry based gethwrapper generation
diff --git a/.changeset/fuzzy-hairs-appear.md b/.changeset/fuzzy-hairs-appear.md
deleted file mode 100644
index a4797462546..00000000000
--- a/.changeset/fuzzy-hairs-appear.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Prometheus observability layer added to OCR3 Reporting Plugins #internal
diff --git a/.changeset/fuzzy-yaks-deny.md b/.changeset/fuzzy-yaks-deny.md
deleted file mode 100644
index 6de0c8d096c..00000000000
--- a/.changeset/fuzzy-yaks-deny.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added Lens Sepolia config
diff --git a/.changeset/giant-eels-jump.md b/.changeset/giant-eels-jump.md
deleted file mode 100644
index 5ab8ca875ca..00000000000
--- a/.changeset/giant-eels-jump.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Add error handling for Arbitrum RPC server timeouts. #added
diff --git a/.changeset/gorgeous-ants-promise.md b/.changeset/gorgeous-ants-promise.md
deleted file mode 100644
index 117bc9a85a9..00000000000
--- a/.changeset/gorgeous-ants-promise.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Updated TXM abandon transaction functionality to drop related attempts. #updated
diff --git a/.changeset/great-peaches-walk.md b/.changeset/great-peaches-walk.md
deleted file mode 100644
index 30e7446bb0c..00000000000
--- a/.changeset/great-peaches-walk.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-fix reported evm node states
diff --git a/.changeset/hot-cats-enjoy.md b/.changeset/hot-cats-enjoy.md
deleted file mode 100644
index 15fc98d9d44..00000000000
--- a/.changeset/hot-cats-enjoy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#added beholder metric to monitor TXMv2 transactions.
diff --git a/.changeset/hot-islands-dress.md b/.changeset/hot-islands-dress.md
deleted file mode 100644
index 82e34ecf42b..00000000000
--- a/.changeset/hot-islands-dress.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal refactor: inject ocr secrets via env instead of config
diff --git a/.changeset/hungry-boats-kneel.md b/.changeset/hungry-boats-kneel.md
new file mode 100644
index 00000000000..f1514cfc4f2
--- /dev/null
+++ b/.changeset/hungry-boats-kneel.md
@@ -0,0 +1,5 @@
+---
+"chainlink": patch
+---
+
+Add telemetry for LLO plugin #added
diff --git a/.changeset/kind-parents-jump.md b/.changeset/kind-parents-jump.md
deleted file mode 100644
index e633f1af1fe..00000000000
--- a/.changeset/kind-parents-jump.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-"chainlink": patch
----
-
-Add two new metrics for monitoring LLO transmitter health #added
-
-`llo_mercurytransmitter_concurrent_transmit_gauge`
-Gauge that measures the number of transmit threads currently waiting on a remote transmit call. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.
-
-`llo_mercurytransmitter_concurrent_delete_gauge`
-Gauge that measures the number of delete threads currently waiting on a delete call to the DB. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.
diff --git a/.changeset/large-ants-occur.md b/.changeset/large-ants-occur.md
deleted file mode 100644
index 81bf4ed5728..00000000000
--- a/.changeset/large-ants-occur.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-add reorg detection for Solana TXM. #added
diff --git a/.changeset/large-fishes-enjoy.md b/.changeset/large-fishes-enjoy.md
deleted file mode 100644
index 201267e8b64..00000000000
--- a/.changeset/large-fishes-enjoy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Fix logic for mapping affected files in CI that affects golangci-lint execution
diff --git a/.changeset/late-doors-battle.md b/.changeset/late-doors-battle.md
deleted file mode 100644
index 8ec64b9048e..00000000000
--- a/.changeset/late-doors-battle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Fix TransactionSender go routine leak. #bugfix
diff --git a/.changeset/late-hornets-yell.md b/.changeset/late-hornets-yell.md
deleted file mode 100644
index 7d04500cc77..00000000000
--- a/.changeset/late-hornets-yell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated Bump chainlink-common version.
diff --git a/.changeset/late-seals-battle.md b/.changeset/late-seals-battle.md
deleted file mode 100644
index 194aa4f380e..00000000000
--- a/.changeset/late-seals-battle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Update deployment address book to support non-evm chains
diff --git a/.changeset/light-trains-chew.md b/.changeset/light-trains-chew.md
deleted file mode 100644
index edbb5a7f7bc..00000000000
--- a/.changeset/light-trains-chew.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Refactor chain ID logic in plugin to be chain agnostic #added
diff --git a/.changeset/long-apples-fold.md b/.changeset/long-apples-fold.md
deleted file mode 100644
index ba3e731951f..00000000000
--- a/.changeset/long-apples-fold.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-DEVSVCS-958: fix automation v2.3 batching bug #bugfix
diff --git a/.changeset/loud-birds-remain.md b/.changeset/loud-birds-remain.md
deleted file mode 100644
index eb1e8f8a9ca..00000000000
--- a/.changeset/loud-birds-remain.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#internal Add unexposed shell cmd for updating a bridge
diff --git a/.changeset/many-crews-wave.md b/.changeset/many-crews-wave.md
deleted file mode 100644
index 328a00e2f48..00000000000
--- a/.changeset/many-crews-wave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal refactor update nodes changeset to support mcms
diff --git a/.changeset/many-nails-explode.md b/.changeset/many-nails-explode.md
deleted file mode 100644
index 43644ef3ec4..00000000000
--- a/.changeset/many-nails-explode.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added core configs
diff --git a/.changeset/mean-dots-move.md b/.changeset/mean-dots-move.md
deleted file mode 100644
index 1169d8379e9..00000000000
--- a/.changeset/mean-dots-move.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Add config var Mercury.Transmitter.TransmitConcurrency #added
diff --git a/.changeset/mean-knives-knock.md b/.changeset/mean-knives-knock.md
deleted file mode 100644
index e04ba4d083f..00000000000
--- a/.changeset/mean-knives-knock.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated chainconfig: show chain type next to key bundle id in UI
diff --git a/.changeset/mean-ravens-stare.md b/.changeset/mean-ravens-stare.md
deleted file mode 100644
index 6b481ae4520..00000000000
--- a/.changeset/mean-ravens-stare.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal add versioned geth wrappers for keystone prod contracts
diff --git a/.changeset/metal-houses-approve.md b/.changeset/metal-houses-approve.md
deleted file mode 100644
index 6768c50767e..00000000000
--- a/.changeset/metal-houses-approve.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Added TxExpirationRebroadcast feature and config for Solana TXM. #added
diff --git a/.changeset/poor-adults-tie.md b/.changeset/poor-adults-tie.md
deleted file mode 100644
index 5d1e7b7fc56..00000000000
--- a/.changeset/poor-adults-tie.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated Explicitly use protoc installed in the makefile.
diff --git a/.changeset/popular-rules-live.md b/.changeset/popular-rules-live.md
deleted file mode 100644
index 2d996a28dc2..00000000000
--- a/.changeset/popular-rules-live.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Fixes a race condition with the Finalizer when clearing txs #bugfix
diff --git a/.changeset/rotten-books-cross.md b/.changeset/rotten-books-cross.md
deleted file mode 100644
index 95231ec47f2..00000000000
--- a/.changeset/rotten-books-cross.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Support multiple streamIDs in stream specs #added
diff --git a/.changeset/serious-suns-flow.md b/.changeset/serious-suns-flow.md
new file mode 100644
index 00000000000..bdf2972551a
--- /dev/null
+++ b/.changeset/serious-suns-flow.md
@@ -0,0 +1,5 @@
+---
+"chainlink": patch
+---
+
+Only show OCR info-level logs with VerboseLogging #internal
diff --git a/.changeset/shaggy-carpets-deliver.md b/.changeset/shaggy-carpets-deliver.md
deleted file mode 100644
index 676ad2fb861..00000000000
--- a/.changeset/shaggy-carpets-deliver.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#removed dead transmission tests
diff --git a/.changeset/sharp-llamas-compete.md b/.changeset/sharp-llamas-compete.md
deleted file mode 100644
index 76808dbdda4..00000000000
--- a/.changeset/sharp-llamas-compete.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#bugfix Fix missing Tron handler
diff --git a/.changeset/shiny-owls-destroy.md b/.changeset/shiny-owls-destroy.md
deleted file mode 100644
index d132d6dbff8..00000000000
--- a/.changeset/shiny-owls-destroy.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"chainlink": patch
----
-
-Logging improvements for LLO
-#internal
diff --git a/.changeset/silver-avocados-buy.md b/.changeset/silver-avocados-buy.md
deleted file mode 100644
index 6b636ee267d..00000000000
--- a/.changeset/silver-avocados-buy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Update MultiNode with latest changes and bug fixes. Fixes an issue that caused nodes to go OutOfSync incorrectly, and also fixed context handling for sending transactions. #internal #bugfix
diff --git a/.changeset/silver-books-grab.md b/.changeset/silver-books-grab.md
deleted file mode 100644
index 2aa20e97f27..00000000000
--- a/.changeset/silver-books-grab.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#add #nops Add soneium config
diff --git a/.changeset/six-camels-smell.md b/.changeset/six-camels-smell.md
new file mode 100644
index 00000000000..a3667ed20e0
--- /dev/null
+++ b/.changeset/six-camels-smell.md
@@ -0,0 +1,5 @@
+---
+"chainlink": minor
+---
+
+Bump to start the next version
diff --git a/.changeset/six-coins-mix.md b/.changeset/six-coins-mix.md
deleted file mode 100644
index 2877aa3012a..00000000000
--- a/.changeset/six-coins-mix.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#bugfix fix: duplicate chain id in chain config dialog
diff --git a/.changeset/soft-rivers-care.md b/.changeset/soft-rivers-care.md
deleted file mode 100644
index 22eeea042ba..00000000000
--- a/.changeset/soft-rivers-care.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-interface change for plugin to support extra args codec, right now noop #added
diff --git a/.changeset/sour-hairs-cross.md b/.changeset/sour-hairs-cross.md
deleted file mode 100644
index fa12a38b5be..00000000000
--- a/.changeset/sour-hairs-cross.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#internal depreciate keystone deployment library
diff --git a/.changeset/spotty-knives-smile.md b/.changeset/spotty-knives-smile.md
deleted file mode 100644
index 8389b72414c..00000000000
--- a/.changeset/spotty-knives-smile.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Increase GasLimit for Automation on ZKsync to 6M #nops
diff --git a/.changeset/spotty-seals-give.md b/.changeset/spotty-seals-give.md
deleted file mode 100644
index 1e3874a783f..00000000000
--- a/.changeset/spotty-seals-give.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Switching CCIP to observed ChainReader for HomeChainReader #internal
diff --git a/.changeset/tall-falcons-yawn.md b/.changeset/tall-falcons-yawn.md
deleted file mode 100644
index 98b90e5994b..00000000000
--- a/.changeset/tall-falcons-yawn.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-#added the ability to define a fallback.toml override config using CL_CHAIN_DEFAULTS env var
diff --git a/.changeset/tame-hats-check.md b/.changeset/tame-hats-check.md
new file mode 100644
index 00000000000..693b26c7ecb
--- /dev/null
+++ b/.changeset/tame-hats-check.md
@@ -0,0 +1,5 @@
+---
+"chainlink": patch
+---
+
+Add missing LINK token addresses #internal
diff --git a/.changeset/thick-vans-tickle.md b/.changeset/thick-vans-tickle.md
deleted file mode 100644
index a719bf8905b..00000000000
--- a/.changeset/thick-vans-tickle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Add support for flexible schemas #added
diff --git a/.changeset/thin-cats-try.md b/.changeset/thin-cats-try.md
deleted file mode 100644
index e7934fe279a..00000000000
--- a/.changeset/thin-cats-try.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Add support for Mercury LLO streams to feeds service. #added
diff --git a/.changeset/thin-emus-wait.md b/.changeset/thin-emus-wait.md
deleted file mode 100644
index 98b91952c27..00000000000
--- a/.changeset/thin-emus-wait.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-fix solana client calls and update solana ref. #internal
diff --git a/.changeset/tiny-kangaroos-switch.md b/.changeset/tiny-kangaroos-switch.md
deleted file mode 100644
index 000f5b6bde5..00000000000
--- a/.changeset/tiny-kangaroos-switch.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Added new fatal error cases for transactions to the Solana TXM. #added
diff --git a/.changeset/tricky-clouds-move.md b/.changeset/tricky-clouds-move.md
deleted file mode 100644
index 8cb50dbb048..00000000000
--- a/.changeset/tricky-clouds-move.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Updated Solana TXM to store prebroadcast transaction errors caught upfront by simulation. Refactored error parsing to more easily introduce new error cases. Optimized storing finalized and errored transaction to minimize memory usage. #updated
diff --git a/.changeset/warm-panthers-stare.md b/.changeset/warm-panthers-stare.md
deleted file mode 100644
index 319a7ad22b3..00000000000
--- a/.changeset/warm-panthers-stare.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Add grpc support for LLO #added
diff --git a/.changeset/wet-bags-clean.md b/.changeset/wet-bags-clean.md
deleted file mode 100644
index 53da05426c9..00000000000
--- a/.changeset/wet-bags-clean.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Change ChainWriter naming to ContractWriter to consolidate Relayer chain interfaces #internal
diff --git a/.changeset/wild-cats-think.md b/.changeset/wild-cats-think.md
deleted file mode 100644
index f56f41b242c..00000000000
--- a/.changeset/wild-cats-think.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-Added the `EVM.Transactions.Enabled` config to enable or disable the transaction manager. #added
diff --git a/.changeset/wild-planes-mix.md b/.changeset/wild-planes-mix.md
deleted file mode 100644
index 1a08c2f9d4d..00000000000
--- a/.changeset/wild-planes-mix.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Truncates workflow name before starting engine
diff --git a/.changeset/wise-buttons-fry.md b/.changeset/wise-buttons-fry.md
deleted file mode 100644
index aa3cb1dab79..00000000000
--- a/.changeset/wise-buttons-fry.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": patch
----
-
-Add TRON integration #added
diff --git a/.changeset/yellow-brooms-leave.md b/.changeset/yellow-brooms-leave.md
deleted file mode 100644
index 638751814bf..00000000000
--- a/.changeset/yellow-brooms-leave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"chainlink": minor
----
-
-#updated feat:create tron chain config on operator ui
diff --git a/.changeset/yellow-dodos-run.md b/.changeset/yellow-dodos-run.md
new file mode 100644
index 00000000000..eddb0bf369d
--- /dev/null
+++ b/.changeset/yellow-dodos-run.md
@@ -0,0 +1,5 @@
+---
+"chainlink": patch
+---
+
+#added Add support for 'standardcapabilities' and 'gateway' jobs to the FMS
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9154f3c0de9..fdb187b8caa 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,6 +1,10 @@
# CODEOWNERS Best Practices
# 1. Per Github docs: "Order is important; the last matching pattern takes the most precedence."
# Please define less specific codeowner paths before more specific codeowner paths in order for the more specific rule to have priority
+# 2. Per Github docs:
+# "create a new file called CODEOWNERS in the .github/, root, or docs/ directory of the repository...
+# ...GitHub will search for them in that order and use the first one it finds."
+# Please put the CODEOWNERS file in .github
# Root
* @smartcontractkit/foundations @smartcontractkit/core
diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml
index 3c727c95aed..707ef8c6027 100644
--- a/.github/e2e-tests.yml
+++ b/.github/e2e-tests.yml
@@ -194,6 +194,8 @@ runner-test-matrix:
pyroscope_env: ci-smoke-capabilities-evm-simulated
test_env_vars:
E2E_TEST_CHAINLINK_VERSION: '{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}' # This is the chainlink version that has the plugins
+ E2E_JD_VERSION: 0.6.0 # there is no latest tag for this repo, so we need to specify the version
+ GITHUB_READ_TOKEN: '{{ env.GITHUB_API_TOKEN }}' # GATI-provided token that can read from capabilities and dev-platform repos
IS_CI: "true"
CTF_CONFIGS: "environment-ci.toml"
# Anvil developer key, not a secret
diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml
index f96328953ec..a0640c5f66d 100644
--- a/.github/integration-in-memory-tests.yml
+++ b/.github/integration-in-memory-tests.yml
@@ -53,7 +53,7 @@ runner-test-matrix:
runs_on: ubuntu-latest
triggers:
- PR Integration CCIP Tests
- test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 12m -test.parallel=2 -count=1 -json
+ test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 25m -test.parallel=2 -count=1 -json
- id: smoke/ccip/ccip_add_chain_test.go:*
path: integration-tests/smoke/ccip/ccip_add_chain_test.go
@@ -111,5 +111,13 @@ runner-test-matrix:
- PR Integration CCIP Tests
test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go -timeout 10m -test.parallel=1 -count=1 -json
+ - id: smoke/ccip/ccip_disable_lane_test.go:*
+ path: integration-tests/smoke/ccip/ccip_disable_lane_test.go
+ test_env_type: in-memory
+ runs_on: ubuntu-latest
+ triggers:
+ - PR Integration CCIP Tests
+ test_cmd: cd integration-tests/smoke/ccip/ && go test ccip_disable_lane_test.go -timeout 10m -test.parallel=1 -count=1 -json
+
# END: CCIP tests
diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml
index a5f6ba609c6..283e04f307b 100644
--- a/.github/workflows/build-publish.yml
+++ b/.github/workflows/build-publish.yml
@@ -59,6 +59,11 @@ jobs:
uses: ./.github/actions/version-file-bump
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Check Tag Signature
+ uses: smartcontractkit/.github/actions/check-if-verified@6319f88a06e307c360dff43c3ac25d0581894a75 # check-if-verified@1.0.0
+ with:
+ tag: ${{ github.ref_name }}
+ assert: true
build-sign-publish-chainlink:
needs: [checks]
@@ -128,18 +133,18 @@ jobs:
) || ''
}}
docker-image-name: >-
- ${{
- github.ref_type == 'tag' &&
+ ${{
+ github.ref_type == 'tag' &&
format(
- '{0}/{1}:{2}',
- env.ECR_HOSTNAME,
+ '{0}/{1}:{2}',
+ env.ECR_HOSTNAME,
needs.checks.outputs.ecr-image-name,
needs.build-sign-publish-chainlink.outputs.docker-image-tag
) || ''
}}
docker-image-digest: >-
- ${{
- github.ref_type == 'tag' &&
+ ${{
+ github.ref_type == 'tag' &&
needs.build-sign-publish-chainlink.outputs.docker-image-digest || ''
}}
crib:
diff --git a/.github/workflows/flakeguard-validate-tests.yml b/.github/workflows/flakeguard-validate-tests.yml
new file mode 100644
index 00000000000..3d8bd3ca6ab
--- /dev/null
+++ b/.github/workflows/flakeguard-validate-tests.yml
@@ -0,0 +1,48 @@
+name: Flakeguard Validate Tests
+
+on:
+ workflow_dispatch:
+ inputs:
+ testPackages:
+ description: 'A comma-separated list of test packages to run.'
+ required: true
+ type: string
+ default: 'github.com/smartcontractkit/chainlink/v2/core/cmd'
+ testRepeatCount:
+ description: 'The number of times to repeat the tests.'
+ required: false
+ type: string
+ default: '5'
+ testRunner:
+ description: 'The default tests runner to use.'
+ required: false
+ type: string
+ default: 'ubuntu-20.04'
+ runTestsWithRace:
+ description: 'Run tests with the race detector enabled.'
+ required: false
+ type: string
+ default: 'true'
+
+jobs:
+ run-custom-tests:
+ name: Run Custom Tests with Flakeguard
+ uses: ./.github/workflows/flakeguard.yml
+ with:
+ repoUrl: 'https://github.com/smartcontractkit/chainlink'
+ projectPath: '.'
+ runAllTests: false
+ # All tests have to pass
+ maxPassRatio: '1.0'
+ extraArgs: >-
+ {
+ "run_custom_test_packages": "${{ inputs.testPackages }}",
+ "test_repeat_count": "${{ inputs.testRepeatCount }}",
+ "run_with_race": "${{ inputs.runTestsWithRace }}",
+ "default_tests_runner": "${{ inputs.testRunner }}",
+ "skipped_tests": ""
+ }
+
+ secrets:
+ SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml
index db5d90bca00..499a0a94bf4 100644
--- a/.github/workflows/flakeguard.yml
+++ b/.github/workflows/flakeguard.yml
@@ -57,10 +57,10 @@ on:
required: true
FLAKEGUARD_SPLUNK_ENDPOINT:
description: "The Splunk HTTP Event Collector (HEC) endpoint."
- required: true
+ required: false
FLAKEGUARD_SPLUNK_HEC:
description: "The Splunk HTTP Event Collector (HEC) token."
- required: true
+ required: false
env:
GIT_BASE_REF: ${{ inputs.baseRef }}
@@ -71,9 +71,10 @@ env:
TEST_REPEAT_COUNT: ${{ fromJSON(inputs.extraArgs)['test_repeat_count'] || '5' }} # The number of times each runner should run a test to detect flaky tests.
RUN_WITH_RACE: ${{ fromJSON(inputs.extraArgs)['run_with_race'] || 'true' }} # Whether to run tests with -race flag.
RUN_WITH_SHUFFLE: ${{ fromJSON(inputs.extraArgs)['run_with_shuffle'] || 'false' }} # Whether to run tests with -shuffle flag.
+ RUN_CUSTOM_TEST_PACKAGES: ${{ fromJSON(inputs.extraArgs)['run_custom_test_packages'] || '' }} # Comma-separated custom test packages to run.
SHUFFLE_SEED: ${{ fromJSON(inputs.extraArgs)['shuffle_seed'] || '999' }} # The seed to use when -shuffle flag is enabled. Requires RUN_WITH_SHUFFLE to be true.
ALL_TESTS_RUNNER: ${{ fromJSON(inputs.extraArgs)['all_tests_runner'] || 'ubuntu22.04-32cores-128GB' }} # The runner to use for running all tests.
- DEFAULT_RUNNER: ${{ fromJSON(inputs.extraArgs)['default_tests_runner'] || 'ubuntu-latest' }} # The runner to use for running custom tests (e.g. in PRs).
+ DEFAULT_RUNNER: ${{ fromJSON(inputs.extraArgs)['default_tests_runner'] || 'ubuntu-latest-8cores-32GB' }} # The runner to use for running custom tests (e.g. in PRs).
UPLOAD_ALL_TEST_RESULTS: ${{ fromJSON(inputs.extraArgs)['upload_all_test_results'] || 'false' }} # Whether to upload all test results as artifacts.
OMIT_TEST_OUTPUTS_ON_SUCCESS: ${{ fromJSON(inputs.extraArgs)['omit_test_outputs_on_success'] || 'true' }}
@@ -135,7 +136,7 @@ jobs:
run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@96581547bab07e3982df522dd4343c998619ca77 # flakguard@0.1.0
- name: Find new or updated test packages
- if: ${{ inputs.runAllTests == false }}
+ if: ${{ inputs.runAllTests == false && env.RUN_CUSTOM_TEST_PACKAGES == '' }}
id: get-tests
shell: bash
env:
@@ -153,7 +154,7 @@ jobs:
echo "packages=$PACKAGES" >> $GITHUB_OUTPUT
- name: Find changed test files
- if: ${{ inputs.runAllTests == false }}
+ if: ${{ inputs.runAllTests == false && env.RUN_CUSTOM_TEST_PACKAGES == '' }}
id: find-changed-test-files
shell: bash
env:
@@ -173,7 +174,11 @@ jobs:
shell: bash
env:
GH_INPUTS_RUN_ALL_TESTS: ${{ inputs.runAllTests }}
+ RUN_CUSTOM_TEST_PACKAGES: ${{ env.RUN_CUSTOM_TEST_PACKAGES }}
run: |
+ # ---------------------------------------------------------
+ # Run all tests if RUN_ALL_TESTS is set
+ # ---------------------------------------------------------
if [[ "$GH_INPUTS_RUN_ALL_TESTS" == "true" ]]; then
# Use ALL_TESTS_RUNNER for a specified number of groups, each with "./..." to run all tests
ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }}
@@ -189,6 +194,30 @@ jobs:
exit 0
fi
+ # ---------------------------------------------------------
+ # If RUN_CUSTOM_TEST_PACKAGES is set, skip diff-based logic and run the specified packages
+ # ---------------------------------------------------------
+ if [[ -n "$RUN_CUSTOM_TEST_PACKAGES" ]]; then
+ IFS=',' read -ra cpkgs <<< "$RUN_CUSTOM_TEST_PACKAGES"
+ groups=()
+
+ for pkg in "${cpkgs[@]}"; do
+ # Trim whitespace around package name
+ pkg=$(echo "$pkg" | xargs)
+ groups+=("{\"testPackages\":\"$pkg\",\"runs_on\":\"${{ env.DEFAULT_RUNNER }}\"}")
+ done
+
+ json_groups=$(printf '%s\n' "${groups[@]}" | jq -s .)
+ echo "$json_groups"
+ echo "matrix<> $GITHUB_OUTPUT
+ echo "$json_groups" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+
+ # -------------------------------------------
+ # Otherwise, use the normal find & split logic
+ # -------------------------------------------
PACKAGES=(${{ steps.get-tests.outputs.packages }})
DESIRED_GROUP_COUNT=$((${{ env.DEFAULT_MAX_RUNNER_COUNT }}))
TOTAL_PACKAGES=${#PACKAGES[@]}
@@ -595,4 +624,4 @@ jobs:
]
}
]
- }
+ }
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bf8606a8e30..a15b54a8f9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -79,6 +79,7 @@ benchmark_report.csv
benchmark_summary.json
secrets.toml
tmp_laneconfig/
+solana_contracts
# goreleaser builds
cosign.*
diff --git a/.goreleaser.develop.yaml b/.goreleaser.develop.yaml
index c633e22fe62..765dab58fc7 100644
--- a/.goreleaser.develop.yaml
+++ b/.goreleaser.develop.yaml
@@ -1,308 +1,300 @@
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 }}
+ - 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"
+ 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
+ - 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
+ - format: binary
snapshot:
- version_template: '{{ .Env.VERSION }}-{{ .ShortCommit }}'
+ version_template: "{{ .Env.VERSION }}-{{ .ShortCommit }}"
checksum:
- name_template: checksums.txt
+ name_template: checksums.txt
dockers:
- - 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
+ - id: linux-amd64-chainlink
+ goos: linux
+ goarch: amd64
+ dockerfile: core/chainlink.goreleaser.Dockerfile
+ image_templates:
+ - "{{ .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-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 }}-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-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:
- - 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'
+ - id: tagged-chainlink
+ name_template: "{{ .Env.IMAGE_PREFIX }}/chainlink:{{ .Env.IMG_TAG }}"
+ image_templates:
+ - "{{ .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-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 }}-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-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:
- disable: "true"
+ disable: "true"
before:
- hooks:
- - cmd: go mod tidy
- - cmd: ./tools/bin/goreleaser_utils before_hook
+ hooks:
+ - cmd: go mod tidy
+ - cmd: ./tools/bin/goreleaser_utils before_hook
partial:
- by: target
+ by: target
nightly:
- version_template: '{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}'
+ version_template: "{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}"
diff --git a/.goreleaser.devspace.yaml b/.goreleaser.devspace.yaml
index 13027590a2b..562bc0e2e0d 100644
--- a/.goreleaser.devspace.yaml
+++ b/.goreleaser.devspace.yaml
@@ -1,102 +1,102 @@
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
+ - 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"
+ 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={{ .Version }}
- flags:
- - -trimpath
- - -buildmode=pie
+ - 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
+ - format: binary
snapshot:
- version_template: v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }}
+ version_template: v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }}
checksum:
- name_template: checksums.txt
+ name_template: checksums.txt
dockers:
- - 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
+ - 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 }}'
+ - name_template: "{{ .Env.IMAGE }}"
+ image_templates:
+ - "{{ .Env.IMAGE }}"
changelog:
- disable: "true"
+ disable: "true"
before:
- hooks:
- - cmd: go mod tidy
- - cmd: ./tools/bin/goreleaser_utils before_hook
+ hooks:
+ - cmd: go mod tidy
+ - cmd: ./tools/bin/goreleaser_utils before_hook
partial:
- by: target
+ by: target
nightly:
- version_template: v0.0.0-{{ .Runtime.Goarch }}-{{ .Now.Format "2006-01-02-15-04-05Z" }}
+ 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
index b4e19d1b31c..8bf860e719c 100644
--- a/.goreleaser.production.yaml
+++ b/.goreleaser.production.yaml
@@ -1,330 +1,322 @@
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 }}
+ - 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"
+ 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
+ - 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
+ - format: tar.gz
snapshot:
- version_template: '{{ .Env.VERSION }}-{{ .ShortCommit }}'
+ version_template: "{{ .Env.VERSION }}-{{ .ShortCommit }}"
checksum:
- name_template: checksums.txt
+ 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
+ - 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 }}-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-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 }}-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-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'
+ - 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 }}-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-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 }}-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-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
+ filters:
+ exclude:
+ - "^docs:"
+ - "^test:"
+ sort: asc
before:
- hooks:
- - cmd: go mod tidy
- - cmd: ./tools/bin/goreleaser_utils before_hook
+ hooks:
+ - cmd: go mod tidy
+ - cmd: ./tools/bin/goreleaser_utils before_hook
sboms:
- - artifacts: archive
+ - artifacts: archive
partial:
- by: target
+ by: target
nightly:
- version_template: '{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}'
+ version_template: "{{ .Env.VERSION }}-{{ .Env.IMG_TAG }}"
diff --git a/.tool-versions b/.tool-versions
index bdf11a7ed21..7c999437710 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -5,6 +5,6 @@ pnpm 9.4.0
postgres 15.1
helm 3.10.3
golangci-lint 1.62.2
-protoc 25.1
+protoc 29.3
python 3.10.5
act 0.2.30
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d5b6332c5a5..16647fb4b9b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,170 @@
# Changelog Chainlink Core
+## 2.20.0 - UNRELEASED
+
+### Minor Changes
+
+- [#15741](https://github.com/smartcontractkit/chainlink/pull/15741) [`37d30814fd`](https://github.com/smartcontractkit/chainlink/commit/37d30814fda19dfc61f7952a691b96036df2ed36) - #updated Gracefully fail if CL_DATABASE_URL is not set.
+
+- [#15699](https://github.com/smartcontractkit/chainlink/pull/15699) [`329e8f02fd`](https://github.com/smartcontractkit/chainlink/commit/329e8f02fdd4becd333878991a4463423082aaba) - #updated feat(job-distributor): support tron chain type on sync
+
+- [#15330](https://github.com/smartcontractkit/chainlink/pull/15330) [`35ef812d7f`](https://github.com/smartcontractkit/chainlink/commit/35ef812d7fc8ccaa31f362980b06b782ce2dcb29) - #removed Remove duplicated testing util for p2p_key only.
+
+- [#15416](https://github.com/smartcontractkit/chainlink/pull/15416) [`dcc6a36763`](https://github.com/smartcontractkit/chainlink/commit/dcc6a367633eedf0ad2f7b054f0892c53d6b4506) - #updated Remove custom ed25519 private to public key conversion.
+
+- [#15307](https://github.com/smartcontractkit/chainlink/pull/15307) [`a3c8092824`](https://github.com/smartcontractkit/chainlink/commit/a3c809282446174c8a13b78e83c3a76a3efca171) - #removed Remove unused ocr1 key files.
+
+- [#15537](https://github.com/smartcontractkit/chainlink/pull/15537) [`c1e92afb86`](https://github.com/smartcontractkit/chainlink/commit/c1e92afb86595ec1d4610974a1566417fa9ee316) - #internal Refactored ChainComponents tests to run in parallel
+
+- [#15996](https://github.com/smartcontractkit/chainlink/pull/15996) [`538b4eb636`](https://github.com/smartcontractkit/chainlink/commit/538b4eb636fc19e539e17d92c579ce96ec8829e0) - #added beholder metric to monitor TXMv2 transactions.
+
+- [#15888](https://github.com/smartcontractkit/chainlink/pull/15888) [`6e09ac75d5`](https://github.com/smartcontractkit/chainlink/commit/6e09ac75d556c8b05099f7dba78e1db79324ac3f) - add reorg detection for Solana TXM. #added
+
+- [#15776](https://github.com/smartcontractkit/chainlink/pull/15776) [`06a44452f9`](https://github.com/smartcontractkit/chainlink/commit/06a44452f9607ac6fb74a3ff05b59fa833c38c91) - Fix logic for mapping affected files in CI that affects golangci-lint execution
+
+- [#15935](https://github.com/smartcontractkit/chainlink/pull/15935) [`d44df0154f`](https://github.com/smartcontractkit/chainlink/commit/d44df0154fb0e0e29d9cd5517d22dedc778a5d3e) - #updated Bump chainlink-common version.
+
+- [#15269](https://github.com/smartcontractkit/chainlink/pull/15269) [`00777b83e1`](https://github.com/smartcontractkit/chainlink/commit/00777b83e1086c2541303926b5063794ec41dc7f) - Update deployment address book to support non-evm chains
+
+- [#15213](https://github.com/smartcontractkit/chainlink/pull/15213) [`1f44f3c40b`](https://github.com/smartcontractkit/chainlink/commit/1f44f3c40b4e49ebd58aea2e2ae60ec7e972776a) - Refactor chain ID logic in plugin to be chain agnostic #added
+
+- [#14326](https://github.com/smartcontractkit/chainlink/pull/14326) [`adf13dc1f1`](https://github.com/smartcontractkit/chainlink/commit/adf13dc1f11e2321a9b67a483c6f1e0594e77c85) - #internal Add unexposed shell cmd for updating a bridge
+
+- [#15323](https://github.com/smartcontractkit/chainlink/pull/15323) [`9eceab5b88`](https://github.com/smartcontractkit/chainlink/commit/9eceab5b88fce2ee23f440f25c0b20df3e1d4b1d) - #updated chainconfig: show chain type next to key bundle id in UI
+
+- [#15437](https://github.com/smartcontractkit/chainlink/pull/15437) [`b368079f5e`](https://github.com/smartcontractkit/chainlink/commit/b368079f5e6205df46b3335d6c2acbea359b2733) - Added TxExpirationRebroadcast feature and config for Solana TXM. #added
+
+- [#16005](https://github.com/smartcontractkit/chainlink/pull/16005) [`eea54da625`](https://github.com/smartcontractkit/chainlink/commit/eea54da625244de1ef14e56738e0a2337e298575) - #updated Explicitly use protoc installed in the makefile.
+
+- [#15565](https://github.com/smartcontractkit/chainlink/pull/15565) [`0fd3c7a828`](https://github.com/smartcontractkit/chainlink/commit/0fd3c7a828ac3701daef2656960fa2c10ba2aeb8) - #removed dead transmission tests
+
+- [#15944](https://github.com/smartcontractkit/chainlink/pull/15944) [`ed5cb0880a`](https://github.com/smartcontractkit/chainlink/commit/ed5cb0880a5c9cb1f31c4ecdadc05b1de0168f17) - interface change for plugin to support extra args codec, right now noop #added
+
+- [#15412](https://github.com/smartcontractkit/chainlink/pull/15412) [`fcc8d3c10c`](https://github.com/smartcontractkit/chainlink/commit/fcc8d3c10c8c8a757f113d9a9acb34997cb935b7) - Add support for Mercury LLO streams to feeds service. #added
+
+- [#15429](https://github.com/smartcontractkit/chainlink/pull/15429) [`030fd7c530`](https://github.com/smartcontractkit/chainlink/commit/030fd7c5309b43148a637fd762bf346467275bc6) - Change ChainWriter naming to ContractWriter to consolidate Relayer chain interfaces #internal
+
+- [#15714](https://github.com/smartcontractkit/chainlink/pull/15714) [`e706d72ab3`](https://github.com/smartcontractkit/chainlink/commit/e706d72ab3a6cf0e718555224ef671fc30b52dbe) - Added the `EVM.Transactions.Enabled` config to enable or disable the transaction manager. #added
+
+- [#15899](https://github.com/smartcontractkit/chainlink/pull/15899) [`796357b17c`](https://github.com/smartcontractkit/chainlink/commit/796357b17ca875ba80e157fc08b0da5db4ed1644) - #updated feat:create tron chain config on operator ui
+
+### Patch Changes
+
+- [#15357](https://github.com/smartcontractkit/chainlink/pull/15357) [`18cb44e891`](https://github.com/smartcontractkit/chainlink/commit/18cb44e891a00edff7486640ffc8e0c9275a04f8) - #updated use real contracts in ccipreader_tests where possible
+
+- [#15573](https://github.com/smartcontractkit/chainlink/pull/15573) [`eaeb2ebe7b`](https://github.com/smartcontractkit/chainlink/commit/eaeb2ebe7bfc53572655be322b793f0bf9556e1e) - #bugfix fix non-idempotent loopp registry.Register
+
+- [#15482](https://github.com/smartcontractkit/chainlink/pull/15482) [`35c2f05853`](https://github.com/smartcontractkit/chainlink/commit/35c2f05853ea1ba28be2c74941674289943b2fe6) - Potential bug introduced from chain selector refactor, not causing issue now since only EVM is used, but need to fix #bugfix
+
+- [#15293](https://github.com/smartcontractkit/chainlink/pull/15293) [`466586309a`](https://github.com/smartcontractkit/chainlink/commit/466586309a8cbbfc1c793ff1021b7fcd3522dd3e) - allow different decimals on different chains for token pools
+
+- [#15271](https://github.com/smartcontractkit/chainlink/pull/15271) [`1231f1417e`](https://github.com/smartcontractkit/chainlink/commit/1231f1417e7fddeca190c2ab037e84c4858181df) - Updated the Solana TXM compute unit limit estimation feature to use the max 1.4M compute unit limit for simulation and enable SigVerify #updated
+
+- [#15321](https://github.com/smartcontractkit/chainlink/pull/15321) [`29eb7554a6`](https://github.com/smartcontractkit/chainlink/commit/29eb7554a62d46f17b7d64674ad01910a03023d1) - Removing ccip-tests/\* dependencies and moving ccip tests under a directory in smoke
+
+- [#15539](https://github.com/smartcontractkit/chainlink/pull/15539) [`49b77048d1`](https://github.com/smartcontractkit/chainlink/commit/49b77048d1b5480a07b9f77b32b005379c679c44) - Adding OCR3 promwrapper to LLO #internal
+
+- [#15858](https://github.com/smartcontractkit/chainlink/pull/15858) [`7debe85cc4`](https://github.com/smartcontractkit/chainlink/commit/7debe85cc458774c0d94c8d2221a9cb17679fbff) - #added Sei config and error mapping
+
+- [#15852](https://github.com/smartcontractkit/chainlink/pull/15852) [`fcefd62068`](https://github.com/smartcontractkit/chainlink/commit/fcefd62068d6be4fea1820d1a9edef4e16fbfa3b) - #internal minor rename of various gethwrappers
+
+- [#15791](https://github.com/smartcontractkit/chainlink/pull/15791) [`2450fff71d`](https://github.com/smartcontractkit/chainlink/commit/2450fff71db772d7e771babb5cbe1a55f5a51f84) - Extract EVM MultiNode to chainlink-framework. #internal
+
+- [#15831](https://github.com/smartcontractkit/chainlink/pull/15831) [`8270318279`](https://github.com/smartcontractkit/chainlink/commit/8270318279ab992328288973f2b831aa9440f6b1) - #internal adding solana devnet to ccip deployment
+
+- [#15921](https://github.com/smartcontractkit/chainlink/pull/15921) [`415343f304`](https://github.com/smartcontractkit/chainlink/commit/415343f304b574d4f024a82e0fad266060c34cf5) - validates response from gateway in workflow/fetcher
+
+- [#15544](https://github.com/smartcontractkit/chainlink/pull/15544) [`036cb20d43`](https://github.com/smartcontractkit/chainlink/commit/036cb20d43b8f2d3cdb4de79d11f97ff63831025) - Reporting number of OCR3 instances running using promwrapper #internal
+
+- [#15950](https://github.com/smartcontractkit/chainlink/pull/15950) [`f9dd7e13bc`](https://github.com/smartcontractkit/chainlink/commit/f9dd7e13bc952e1f006f7e5c663b0953aa565cce) - Prevents a panic in test helper for confirming transaction
+ and adds encrypted public key to a peer before calling addNodes
+ on CapabilitiesRegistry
+
+- [#15121](https://github.com/smartcontractkit/chainlink/pull/15121) [`5d22ba8dd2`](https://github.com/smartcontractkit/chainlink/commit/5d22ba8dd2269b11e024e3bc93fc90225034abf7) - #added Adding 5 chains (B^2, BoB, Berachain, Unichain, Worldchain configs)
+
+- [#15735](https://github.com/smartcontractkit/chainlink/pull/15735) [`7743429082`](https://github.com/smartcontractkit/chainlink/commit/7743429082e6c404d6db1877242b747ddd5f6e40) - Reduce PriceMin on Avalanche to 1 gwei #nops
+
+- [#15846](https://github.com/smartcontractkit/chainlink/pull/15846) [`6aa365d600`](https://github.com/smartcontractkit/chainlink/commit/6aa365d600b0f7b9473344942adb9f04f9fb4106) - Add panic recovery to wsrpc mercury client
+
+ - Should help to make nodes running wsrpc v0.8.2 more stable #bugfix
+
+- [#15913](https://github.com/smartcontractkit/chainlink/pull/15913) [`d0a7df39f0`](https://github.com/smartcontractkit/chainlink/commit/d0a7df39f0391b15d67ba5f4ad2268d40d0b3359) - #bugfix Add chaintype.ChainZircuit to chaintypes with rollup support in L1 oracle to prevent a nil L1 oracle being used for Zircuit's gas estimator
+
+- [#15690](https://github.com/smartcontractkit/chainlink/pull/15690) [`ed6f486d59`](https://github.com/smartcontractkit/chainlink/commit/ed6f486d59c2cbdfa02c6fbfc3a42fb6d5f805a2) - #added stream job delete capability
+
+- [#15605](https://github.com/smartcontractkit/chainlink/pull/15605) [`8c65527c82`](https://github.com/smartcontractkit/chainlink/commit/8c65527c82a20c74b2a4707221ef496802b21804) - Changed RMNRemote and RMNHome parameter f to fObserve and fSign #updated
+
+- [#15829](https://github.com/smartcontractkit/chainlink/pull/15829) [`6e65deecae`](https://github.com/smartcontractkit/chainlink/commit/6e65deecae053ee1e885da7ce6d1d308364ced1d) - #internal change gethwrapper to allow for foundry based gethwrapper generation
+
+- [#15521](https://github.com/smartcontractkit/chainlink/pull/15521) [`f6f2457d93`](https://github.com/smartcontractkit/chainlink/commit/f6f2457d9367c543bef20491a26785266849c154) - Prometheus observability layer added to OCR3 Reporting Plugins #internal
+
+- [#15624](https://github.com/smartcontractkit/chainlink/pull/15624) [`8f6c3b461b`](https://github.com/smartcontractkit/chainlink/commit/8f6c3b461b05b4686b98d31a3c85df078328d526) - #added Lens Sepolia config
+
+- [#15488](https://github.com/smartcontractkit/chainlink/pull/15488) [`52f364a6cd`](https://github.com/smartcontractkit/chainlink/commit/52f364a6cd842fe63c4cab6182f4c9fbbf7d134e) - Add error handling for Arbitrum RPC server timeouts. #added
+
+- [#15616](https://github.com/smartcontractkit/chainlink/pull/15616) [`c57f910327`](https://github.com/smartcontractkit/chainlink/commit/c57f910327ad2a0cb104a156b289f75b5bb7d972) - Updated TXM abandon transaction functionality to drop related attempts. #updated
+
+- [#15339](https://github.com/smartcontractkit/chainlink/pull/15339) [`0cabe54f85`](https://github.com/smartcontractkit/chainlink/commit/0cabe54f8535a466a5404bac67396071ec058d94) - fix reported evm node states
+
+- [#15470](https://github.com/smartcontractkit/chainlink/pull/15470) [`54938d4ad2`](https://github.com/smartcontractkit/chainlink/commit/54938d4ad2b430d4941eaae711abe5e1e6a7686a) - #internal refactor: inject ocr secrets via env instead of config
+
+- [#15362](https://github.com/smartcontractkit/chainlink/pull/15362) [`6ea458859f`](https://github.com/smartcontractkit/chainlink/commit/6ea458859f19835d671455c5ce48a5d91cc9d6aa) - Add two new metrics for monitoring LLO transmitter health #added
+
+ `llo_mercurytransmitter_concurrent_transmit_gauge`
+ Gauge that measures the number of transmit threads currently waiting on a remote transmit call. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.
+
+ `llo_mercurytransmitter_concurrent_delete_gauge`
+ Gauge that measures the number of delete threads currently waiting on a delete call to the DB. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.
+
+- [#15425](https://github.com/smartcontractkit/chainlink/pull/15425) [`f094f6c550`](https://github.com/smartcontractkit/chainlink/commit/f094f6c550df43b761d71fdf10cc70bf71a7a318) - Fix TransactionSender go routine leak. #bugfix
+
+- [#15897](https://github.com/smartcontractkit/chainlink/pull/15897) [`47a0c4227c`](https://github.com/smartcontractkit/chainlink/commit/47a0c4227c1ccdd93a7b0a6365e7e1c78c74b6d7) - DEVSVCS-958: fix automation v2.3 batching bug #bugfix
+
+- [#15543](https://github.com/smartcontractkit/chainlink/pull/15543) [`7b6e20f1b4`](https://github.com/smartcontractkit/chainlink/commit/7b6e20f1b40506467349eb0203178aa2c51f5d41) - #internal refactor update nodes changeset to support mcms
+
+- [#15985](https://github.com/smartcontractkit/chainlink/pull/15985) [`87e0fdfaac`](https://github.com/smartcontractkit/chainlink/commit/87e0fdfaac5cc80b571c5ed4d5837576279daa27) - #added core configs
+
+- [#15169](https://github.com/smartcontractkit/chainlink/pull/15169) [`1341a3a39b`](https://github.com/smartcontractkit/chainlink/commit/1341a3a39be8987bae7318f7f3dba0e9b0f31c49) - Add config var Mercury.Transmitter.TransmitConcurrency #added
+
+- [#15785](https://github.com/smartcontractkit/chainlink/pull/15785) [`cb36e64cb1`](https://github.com/smartcontractkit/chainlink/commit/cb36e64cb14e6c67967d667b2b37f00bbba11ab0) - #internal add versioned geth wrappers for keystone prod contracts
+
+- [#15457](https://github.com/smartcontractkit/chainlink/pull/15457) [`f6dfb4e87b`](https://github.com/smartcontractkit/chainlink/commit/f6dfb4e87b8cf58ccb2646737f354f2453d07940) - Fixes a race condition with the Finalizer when clearing txs #bugfix
+
+- [#15603](https://github.com/smartcontractkit/chainlink/pull/15603) [`c7759e15e2`](https://github.com/smartcontractkit/chainlink/commit/c7759e15e2b15bdeacf00ddbd433a4b420072cf3) - Support multiple streamIDs in stream specs #added
+
+- [#15932](https://github.com/smartcontractkit/chainlink/pull/15932) [`186fda8dc3`](https://github.com/smartcontractkit/chainlink/commit/186fda8dc3c4bae8abc436efc0e64d44b86b7628) - #bugfix Fix missing Tron handler
+
+- [#15169](https://github.com/smartcontractkit/chainlink/pull/15169) [`1341a3a39b`](https://github.com/smartcontractkit/chainlink/commit/1341a3a39be8987bae7318f7f3dba0e9b0f31c49) - Logging improvements for LLO
+ #internal
+
+- [#15058](https://github.com/smartcontractkit/chainlink/pull/15058) [`d4d1456cc7`](https://github.com/smartcontractkit/chainlink/commit/d4d1456cc7d4b0828c1b5e270857636762680e04) - Update MultiNode with latest changes and bug fixes. Fixes an issue that caused nodes to go OutOfSync incorrectly, and also fixed context handling for sending transactions. #internal #bugfix
+
+- [#15883](https://github.com/smartcontractkit/chainlink/pull/15883) [`182575a823`](https://github.com/smartcontractkit/chainlink/commit/182575a823d8e011f4a03a8a69d5498ef5346019) - #add #nops Add soneium config
+
+- [#15585](https://github.com/smartcontractkit/chainlink/pull/15585) [`99b666fbcb`](https://github.com/smartcontractkit/chainlink/commit/99b666fbcbccb926e6dbac11896bf7e7ee5c25ea) - #bugfix fix: duplicate chain id in chain config dialog
+
+- [#15759](https://github.com/smartcontractkit/chainlink/pull/15759) [`0b8172dfcc`](https://github.com/smartcontractkit/chainlink/commit/0b8172dfcc9bc5ca3c166139286b9675239250c8) - #internal depreciate keystone deployment library
+
+- [#15474](https://github.com/smartcontractkit/chainlink/pull/15474) [`b0ea0ca066`](https://github.com/smartcontractkit/chainlink/commit/b0ea0ca0665ef5ebd2136fe4392c8b3ee7f49d12) - Increase GasLimit for Automation on ZKsync to 6M #nops
+
+- [#15628](https://github.com/smartcontractkit/chainlink/pull/15628) [`6101be751e`](https://github.com/smartcontractkit/chainlink/commit/6101be751e8c1088e53bcf7e1c2481f4215d420f) - Switching CCIP to observed ChainReader for HomeChainReader #internal
+
+- [#15617](https://github.com/smartcontractkit/chainlink/pull/15617) [`5b503a3c02`](https://github.com/smartcontractkit/chainlink/commit/5b503a3c02801809533012cd73b5f7c492f73ac8) - #added the ability to define a fallback.toml override config using CL_CHAIN_DEFAULTS env var
+
+- [#15493](https://github.com/smartcontractkit/chainlink/pull/15493) [`16eeb3b5de`](https://github.com/smartcontractkit/chainlink/commit/16eeb3b5de6526f4a53bad2d38be581506cdbfd1) - Add support for flexible schemas #added
+
+- [#16010](https://github.com/smartcontractkit/chainlink/pull/16010) [`5dd3d80200`](https://github.com/smartcontractkit/chainlink/commit/5dd3d80200a7f5528998cca1ac038d33bab70593) - fix solana client calls and update solana ref. #internal
+
+- [#15604](https://github.com/smartcontractkit/chainlink/pull/15604) [`5f3aa78bce`](https://github.com/smartcontractkit/chainlink/commit/5f3aa78bce9f13f5bee26b8a53cb5a1f14ea9102) - Added new fatal error cases for transactions to the Solana TXM. #added
+
+- [#15369](https://github.com/smartcontractkit/chainlink/pull/15369) [`cb194d72a4`](https://github.com/smartcontractkit/chainlink/commit/cb194d72a4ea88831eaf7e6505c582f6dc312d27) - Updated Solana TXM to store prebroadcast transaction errors caught upfront by simulation. Refactored error parsing to more easily introduce new error cases. Optimized storing finalized and errored transaction to minimize memory usage. #updated
+
+- [#15924](https://github.com/smartcontractkit/chainlink/pull/15924) [`50c7453965`](https://github.com/smartcontractkit/chainlink/commit/50c745396596a40e230ffcb4681788440b6df908) - Add grpc support for LLO #added
+
+- [#15896](https://github.com/smartcontractkit/chainlink/pull/15896) [`9fab5114b5`](https://github.com/smartcontractkit/chainlink/commit/9fab5114b59c0c5dbb29b7c2af5ca5f035ea13d0) - Truncates workflow name before starting engine
+
+- [#14783](https://github.com/smartcontractkit/chainlink/pull/14783) [`0199523f90`](https://github.com/smartcontractkit/chainlink/commit/0199523f9042d58c87ea2909e10e7468aa5b36c1) - Add TRON integration #added
+
## 2.19.0 - 2024-12-12
### Minor Changes
diff --git a/GNUmakefile b/GNUmakefile
index 27fa4270497..a7ced725619 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -111,7 +111,7 @@ abigen: ## Build & install abigen.
.PHONY: generate
generate: abigen codecgen mockery protoc gomods ## Execute all go:generate commands.
## Updating PATH makes sure that go:generate uses the version of protoc installed by the protoc make command.
- export PATH=$(HOME)/.local/bin:$(PATH); gomods -w go generate -x ./...
+ export PATH="$(HOME)/.local/bin:$(PATH)"; gomods -w go generate -x ./...
find . -type f -name .mockery.yaml -execdir mockery \; ## Execute mockery for all .mockery.yaml files
.PHONY: rm-mocked
@@ -168,7 +168,7 @@ codecgen: $(codecgen) ## Install codecgen
.PHONY: protoc
protoc: ## Install protoc
- core/scripts/install-protoc.sh 25.1 /
+ core/scripts/install-protoc.sh 29.3 /
go install google.golang.org/protobuf/cmd/protoc-gen-go@`go list -m -json google.golang.org/protobuf | jq -r .Version`
go install github.com/smartcontractkit/wsrpc/cmd/protoc-gen-go-wsrpc@`go list -m -json github.com/smartcontractkit/wsrpc | jq -r .Version`
@@ -199,6 +199,18 @@ modgraph:
test-short: ## Run 'go test -short' and suppress uninteresting output
go test -short ./... | grep -v "\[no test files\]" | grep -v "\(cached\)"
+.PHONY: run_flakeguard_validate_tests
+run_flakeguard_validate_tests:
+ @read -p "Enter a comma-separated list of test packages (e.g., package1,package2): " PKGS; \
+ read -p "Enter the number of times to rerun the tests (e.g., 5): " REPS; \
+ read -p "Enter the test runner (default: ubuntu-20.04): " RUNNER; \
+ RUNNER=$${RUNNER:-ubuntu-20.04}; \
+ gh workflow run flakeguard-validate-tests.yml \
+ -f testPackages="$${PKGS}" \
+ -f testRepeatCount="$${REPS}" \
+ -f runTestsWithRace="true" \
+ -f testRunner="$${RUNNER}"
+
help:
@echo ""
@echo " .__ .__ .__ .__ __"
diff --git a/ccip/config/evm/BSC_Mainnet.toml b/ccip/config/evm/BSC_Mainnet.toml
index e95f0af1eb7..45bc2cb598f 100644
--- a/ccip/config/evm/BSC_Mainnet.toml
+++ b/ccip/config/evm/BSC_Mainnet.toml
@@ -4,27 +4,3 @@
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'
-# 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
-
-[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
index b27a877812b..9ed37c88a82 100644
--- a/ccip/config/evm/BSC_Testnet.toml
+++ b/ccip/config/evm/BSC_Testnet.toml
@@ -4,30 +4,3 @@
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
-
-[OCR]
-DatabaseTimeout = '2s'
-ContractTransmitterTransmitTimeout = '2s'
-ObservationGracePeriod = '500ms'
-
-[NodePool]
-SyncThreshold = 10
diff --git a/ccip/config/evm/zkSync_Mainnet.toml b/ccip/config/evm/ZKsync_Mainnet.toml
similarity index 100%
rename from ccip/config/evm/zkSync_Mainnet.toml
rename to ccip/config/evm/ZKsync_Mainnet.toml
diff --git a/ccip/config/evm/zkSync_Sepolia.toml b/ccip/config/evm/ZKsync_Sepolia.toml
similarity index 100%
rename from ccip/config/evm/zkSync_Sepolia.toml
rename to ccip/config/evm/ZKsync_Sepolia.toml
diff --git a/ccip/config/evm/fallback.toml b/ccip/config/evm/fallback.toml
index 86ec56dd0b7..c5d77c7a884 100644
--- a/ccip/config/evm/fallback.toml
+++ b/ccip/config/evm/fallback.toml
@@ -67,7 +67,7 @@ CacheTimeout = '10s'
[HeadTracker]
HistoryDepth = 100
MaxBufferSize = 3
-SamplingInterval = '1s'
+SamplingInterval = '5s'
FinalityTagBypass = true
MaxAllowedFinalityDepth = 10000
PersistenceEnabled = true
diff --git a/common/txmgr/types/mocks/key_store.go b/common/txmgr/types/mocks/key_store.go
index 4d9508919f3..050128eaa54 100644
--- a/common/txmgr/types/mocks/key_store.go
+++ b/common/txmgr/types/mocks/key_store.go
@@ -11,20 +11,20 @@ import (
)
// KeyStore is an autogenerated mock type for the KeyStore type
-type KeyStore[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence] struct {
+type KeyStore[ADDR chains.Hashable, CHAIN_ID chains.ID] struct {
mock.Mock
}
-type KeyStore_Expecter[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence] struct {
+type KeyStore_Expecter[ADDR chains.Hashable, CHAIN_ID chains.ID] struct {
mock *mock.Mock
}
-func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) EXPECT() *KeyStore_Expecter[ADDR, CHAIN_ID, SEQ] {
- return &KeyStore_Expecter[ADDR, CHAIN_ID, SEQ]{mock: &_m.Mock}
+func (_m *KeyStore[ADDR, CHAIN_ID]) EXPECT() *KeyStore_Expecter[ADDR, CHAIN_ID] {
+ return &KeyStore_Expecter[ADDR, CHAIN_ID]{mock: &_m.Mock}
}
// CheckEnabled provides a mock function with given fields: ctx, address, chainID
-func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) CheckEnabled(ctx context.Context, address ADDR, chainID CHAIN_ID) error {
+func (_m *KeyStore[ADDR, CHAIN_ID]) CheckEnabled(ctx context.Context, address ADDR, chainID CHAIN_ID) error {
ret := _m.Called(ctx, address, chainID)
if len(ret) == 0 {
@@ -42,7 +42,7 @@ func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) CheckEnabled(ctx context.Context, addre
}
// KeyStore_CheckEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckEnabled'
-type KeyStore_CheckEnabled_Call[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence] struct {
+type KeyStore_CheckEnabled_Call[ADDR chains.Hashable, CHAIN_ID chains.ID] struct {
*mock.Call
}
@@ -50,30 +50,30 @@ type KeyStore_CheckEnabled_Call[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ ch
// - ctx context.Context
// - address ADDR
// - chainID CHAIN_ID
-func (_e *KeyStore_Expecter[ADDR, CHAIN_ID, SEQ]) CheckEnabled(ctx interface{}, address interface{}, chainID interface{}) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ] {
- return &KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ]{Call: _e.mock.On("CheckEnabled", ctx, address, chainID)}
+func (_e *KeyStore_Expecter[ADDR, CHAIN_ID]) CheckEnabled(ctx interface{}, address interface{}, chainID interface{}) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID] {
+ return &KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID]{Call: _e.mock.On("CheckEnabled", ctx, address, chainID)}
}
-func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ]) Run(run func(ctx context.Context, address ADDR, chainID CHAIN_ID)) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID]) Run(run func(ctx context.Context, address ADDR, chainID CHAIN_ID)) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID] {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(ADDR), args[2].(CHAIN_ID))
})
return _c
}
-func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ]) Return(_a0 error) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID]) Return(_a0 error) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID] {
_c.Call.Return(_a0)
return _c
}
-func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ]) RunAndReturn(run func(context.Context, ADDR, CHAIN_ID) error) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID]) RunAndReturn(run func(context.Context, ADDR, CHAIN_ID) error) *KeyStore_CheckEnabled_Call[ADDR, CHAIN_ID] {
_c.Call.Return(run)
return _c
}
-// EnabledAddressesForChain provides a mock function with given fields: ctx, chainId
-func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) EnabledAddressesForChain(ctx context.Context, chainId CHAIN_ID) ([]ADDR, error) {
- ret := _m.Called(ctx, chainId)
+// EnabledAddressesForChain provides a mock function with given fields: ctx, chainID
+func (_m *KeyStore[ADDR, CHAIN_ID]) EnabledAddressesForChain(ctx context.Context, chainID CHAIN_ID) ([]ADDR, error) {
+ ret := _m.Called(ctx, chainID)
if len(ret) == 0 {
panic("no return value specified for EnabledAddressesForChain")
@@ -82,10 +82,10 @@ func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) EnabledAddressesForChain(ctx context.Co
var r0 []ADDR
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) ([]ADDR, error)); ok {
- return rf(ctx, chainId)
+ return rf(ctx, chainID)
}
if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) []ADDR); ok {
- r0 = rf(ctx, chainId)
+ r0 = rf(ctx, chainID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]ADDR)
@@ -93,7 +93,7 @@ func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) EnabledAddressesForChain(ctx context.Co
}
if rf, ok := ret.Get(1).(func(context.Context, CHAIN_ID) error); ok {
- r1 = rf(ctx, chainId)
+ r1 = rf(ctx, chainID)
} else {
r1 = ret.Error(1)
}
@@ -102,36 +102,36 @@ func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) EnabledAddressesForChain(ctx context.Co
}
// KeyStore_EnabledAddressesForChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnabledAddressesForChain'
-type KeyStore_EnabledAddressesForChain_Call[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence] struct {
+type KeyStore_EnabledAddressesForChain_Call[ADDR chains.Hashable, CHAIN_ID chains.ID] struct {
*mock.Call
}
// EnabledAddressesForChain is a helper method to define mock.On call
// - ctx context.Context
-// - chainId CHAIN_ID
-func (_e *KeyStore_Expecter[ADDR, CHAIN_ID, SEQ]) EnabledAddressesForChain(ctx interface{}, chainId interface{}) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ] {
- return &KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ]{Call: _e.mock.On("EnabledAddressesForChain", ctx, chainId)}
+// - chainID CHAIN_ID
+func (_e *KeyStore_Expecter[ADDR, CHAIN_ID]) EnabledAddressesForChain(ctx interface{}, chainID interface{}) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID] {
+ return &KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID]{Call: _e.mock.On("EnabledAddressesForChain", ctx, chainID)}
}
-func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ]) Run(run func(ctx context.Context, chainId CHAIN_ID)) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID]) Run(run func(ctx context.Context, chainID CHAIN_ID)) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID] {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(CHAIN_ID))
})
return _c
}
-func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ]) Return(_a0 []ADDR, _a1 error) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID]) Return(_a0 []ADDR, _a1 error) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID] {
_c.Call.Return(_a0, _a1)
return _c
}
-func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ]) RunAndReturn(run func(context.Context, CHAIN_ID) ([]ADDR, error)) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID]) RunAndReturn(run func(context.Context, CHAIN_ID) ([]ADDR, error)) *KeyStore_EnabledAddressesForChain_Call[ADDR, CHAIN_ID] {
_c.Call.Return(run)
return _c
}
// SubscribeToKeyChanges provides a mock function with given fields: ctx
-func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) SubscribeToKeyChanges(ctx context.Context) (chan struct{}, func()) {
+func (_m *KeyStore[ADDR, CHAIN_ID]) SubscribeToKeyChanges(ctx context.Context) (chan struct{}, func()) {
ret := _m.Called(ctx)
if len(ret) == 0 {
@@ -163,40 +163,40 @@ func (_m *KeyStore[ADDR, CHAIN_ID, SEQ]) SubscribeToKeyChanges(ctx context.Conte
}
// KeyStore_SubscribeToKeyChanges_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeToKeyChanges'
-type KeyStore_SubscribeToKeyChanges_Call[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence] struct {
+type KeyStore_SubscribeToKeyChanges_Call[ADDR chains.Hashable, CHAIN_ID chains.ID] struct {
*mock.Call
}
// SubscribeToKeyChanges is a helper method to define mock.On call
// - ctx context.Context
-func (_e *KeyStore_Expecter[ADDR, CHAIN_ID, SEQ]) SubscribeToKeyChanges(ctx interface{}) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ] {
- return &KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ]{Call: _e.mock.On("SubscribeToKeyChanges", ctx)}
+func (_e *KeyStore_Expecter[ADDR, CHAIN_ID]) SubscribeToKeyChanges(ctx interface{}) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID] {
+ return &KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID]{Call: _e.mock.On("SubscribeToKeyChanges", ctx)}
}
-func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ]) Run(run func(ctx context.Context)) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID]) Run(run func(ctx context.Context)) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID] {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
-func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ]) Return(ch chan struct{}, unsub func()) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID]) Return(ch chan struct{}, unsub func()) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID] {
_c.Call.Return(ch, unsub)
return _c
}
-func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ]) RunAndReturn(run func(context.Context) (chan struct{}, func())) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID, SEQ] {
+func (_c *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID]) RunAndReturn(run func(context.Context) (chan struct{}, func())) *KeyStore_SubscribeToKeyChanges_Call[ADDR, CHAIN_ID] {
_c.Call.Return(run)
return _c
}
// NewKeyStore creates a new instance of KeyStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
-func NewKeyStore[ADDR chains.Hashable, CHAIN_ID chains.ID, SEQ chains.Sequence](t interface {
+func NewKeyStore[ADDR chains.Hashable, CHAIN_ID chains.ID](t interface {
mock.TestingT
Cleanup(func())
-}) *KeyStore[ADDR, CHAIN_ID, SEQ] {
- mock := &KeyStore[ADDR, CHAIN_ID, SEQ]{}
+}) *KeyStore[ADDR, CHAIN_ID] {
+ mock := &KeyStore[ADDR, CHAIN_ID]{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
diff --git a/contracts/.changeset/gold-items-dance.md b/contracts/.changeset/gold-items-dance.md
new file mode 100644
index 00000000000..0da36b92c8f
--- /dev/null
+++ b/contracts/.changeset/gold-items-dance.md
@@ -0,0 +1,10 @@
+---
+'@chainlink/contracts': patch
+---
+
+#internal move multiple weth9 implementations to vendor
+
+
+PR issue: CCIP-5081
+
+Solidity Review issue: CCIP-3966
\ No newline at end of file
diff --git a/contracts/.changeset/quiet-masks-act.md b/contracts/.changeset/quiet-masks-act.md
new file mode 100644
index 00000000000..7a987553d9d
--- /dev/null
+++ b/contracts/.changeset/quiet-masks-act.md
@@ -0,0 +1,10 @@
+---
+'@chainlink/contracts': patch
+---
+
+Comment and parameter validation fixes and remove outstandingTokens from BurnToAddressMintTokenPool #bugfix
+
+
+PR issue: CCIP-5061
+
+Solidity Review issue: CCIP-3966
\ No newline at end of file
diff --git a/contracts/.changeset/seven-worms-yawn.md b/contracts/.changeset/seven-worms-yawn.md
new file mode 100644
index 00000000000..3a8674a9d68
--- /dev/null
+++ b/contracts/.changeset/seven-worms-yawn.md
@@ -0,0 +1,10 @@
+---
+'@chainlink/contracts': patch
+---
+
+#internal Minor FeeQuoter audit fixes
+
+PR issue: CCIP-5046
+
+
+Solidity Review issue: CCIP-3966
\ No newline at end of file
diff --git a/contracts/.changeset/smart-bats-repair.md b/contracts/.changeset/smart-bats-repair.md
new file mode 100644
index 00000000000..220880ef2b1
--- /dev/null
+++ b/contracts/.changeset/smart-bats-repair.md
@@ -0,0 +1,5 @@
+---
+'@chainlink/contracts': patch
+---
+
+Update mayberevertmessagereceiver contract to emit message received event and allow token withdrawal
diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot
index ad9849b7e47..130c747ab21 100644
--- a/contracts/gas-snapshots/ccip.gas-snapshot
+++ b/contracts/gas-snapshots/ccip.gas-snapshot
@@ -4,12 +4,10 @@ BurnMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 236872)
BurnMintTokenPool_lockOrBurn:test_Setup() (gas: 17819)
BurnMintTokenPool_releaseOrMint:test_PoolMint() (gas: 102527)
BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData() (gas: 237292)
-BurnToAddressMintTokenPool_lockOrBurn:test_LockOrBurn() (gas: 257956)
-BurnToAddressMintTokenPool_releaseOrMint:test_releaseOrMint() (gas: 126048)
-BurnToAddressMintTokenPool_setOutstandingokens:test_setOutstandingTokens() (gas: 37793)
+BurnToAddressMintTokenPool_lockOrBurn:test_LockOrBurn() (gas: 235440)
BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 239012)
BurnWithFromMintTokenPool_lockOrBurn:test_Setup() (gas: 24169)
-CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2079856)
+CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2079619)
CCIPHome__validateConfig:test__validateConfig() (gas: 300016)
CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners() (gas: 332965)
CCIPHome__validateConfig:test__validateConfigSmallerFChain() (gas: 459322)
@@ -27,8 +25,8 @@ CCIPHome_setCandidate:test_setCandidate() (gas: 1365392)
CCIPHome_supportsInterface:test_supportsInterface() (gas: 9885)
DefensiveExampleTest:test_HappyPath() (gas: 200535)
DefensiveExampleTest:test_Recovery() (gas: 424996)
-E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1496066)
-ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10445)
+E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1514547)
+ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10517)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96964)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49797)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17460)
@@ -62,82 +60,82 @@ FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval() (gas: 44421)
FactoryBurnMintERC20_mint:test_BasicMint() (gas: 149826)
FactoryBurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11539)
FactoryBurnMintERC20_transfer:test_Transfer() (gas: 42505)
-FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 149063)
-FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput() (gas: 12493)
-FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates() (gas: 162480)
+FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 149279)
+FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput() (gas: 12515)
+FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates() (gas: 162585)
FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() (gas: 54881)
FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() (gas: 45364)
FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12468)
-FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88604)
-FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13196)
-FeeQuoter_constructor:test_Setup() (gas: 5429233)
+FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88736)
+FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13218)
+FeeQuoter_constructor:test_Setup() (gas: 5447819)
FeeQuoter_convertTokenAmount:test_ConvertTokenAmount() (gas: 68417)
-FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 98884)
-FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21505)
-FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14904)
+FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 98860)
+FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21439)
+FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14816)
FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices() (gas: 73123)
-FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 113576)
-FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 110663)
+FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 113706)
+FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 110793)
FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed() (gas: 68158)
-FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent() (gas: 33546)
-FeeQuoter_getTokenPrices:test_GetTokenPrices() (gas: 78534)
-FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee() (gas: 34616)
-FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee() (gas: 32395)
-FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas() (gas: 25465)
-FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee() (gas: 91728)
-FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee() (gas: 17904)
-FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas() (gas: 25272)
-FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas() (gas: 25295)
-FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 37853)
-FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults() (gas: 26989)
-FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 85158)
-FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 243094)
-FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 143736)
-FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 115240)
-FeeQuoter_getValidatedFee:test_SolChainFamilySelector() (gas: 60999)
-FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 66233)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice() (gas: 58905)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed() (gas: 65115)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() (gas: 1897724)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() (gas: 1897766)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() (gas: 1877822)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() (gas: 1897564)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals() (gas: 1897700)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value() (gas: 1897534)
-FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() (gas: 65233)
-FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken() (gas: 61854)
-FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52565)
-FeeQuoter_onReport:test_onReport() (gas: 88942)
-FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122570)
-FeeQuoter_parseSVMExtraArgsFromBytes:test_SVMExtraArgsV1() (gas: 23233)
+FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent() (gas: 33568)
+FeeQuoter_getTokenPrices:test_GetTokenPrices() (gas: 78556)
+FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee() (gas: 34551)
+FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee() (gas: 32330)
+FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas() (gas: 25400)
+FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee() (gas: 91599)
+FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee() (gas: 17817)
+FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas() (gas: 25207)
+FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas() (gas: 25230)
+FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 37788)
+FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults() (gas: 26924)
+FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 84896)
+FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 242832)
+FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 143454)
+FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 114959)
+FeeQuoter_getValidatedFee:test_SolChainFamilySelector() (gas: 61180)
+FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 66298)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice() (gas: 58927)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed() (gas: 65137)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() (gas: 1897746)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() (gas: 1897788)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() (gas: 1877844)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() (gas: 1897586)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals() (gas: 1897722)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value() (gas: 1897556)
+FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() (gas: 65255)
+FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken() (gas: 61876)
+FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52609)
+FeeQuoter_onReport:test_onReport() (gas: 88964)
+FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122592)
+FeeQuoter_parseSVMExtraArgsFromBytes:test_SVMExtraArgsV1() (gas: 23255)
FeeQuoter_parseSVMExtraArgsFromBytes:test_SVMExtraArgsV1TagSelector() (gas: 3157)
-FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorEVM() (gas: 19457)
-FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_NoTokenTransfer() (gas: 22644)
-FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_WithTokenTransfer() (gas: 22633)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 29003)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 33038)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 77567)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28634)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26494)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 22700)
-FeeQuoter_processMessageArgs:test_processMessageArgs_WithSVMExtraArgsV1() (gas: 63415)
-FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsDefault() (gas: 17113)
-FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV1() (gas: 16180)
+FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorEVM() (gas: 19479)
+FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_NoTokenTransfer() (gas: 22666)
+FeeQuoter_processChainFamilySelector:test_processChainFamilySelectorSVM_WithTokenTransfer() (gas: 22655)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 29047)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 33060)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 77633)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28678)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26538)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 22722)
+FeeQuoter_processMessageArgs:test_processMessageArgs_WithSVMExtraArgsV1() (gas: 63617)
+FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsDefault() (gas: 17135)
+FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV1() (gas: 16202)
FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV1TagSelector() (gas: 3169)
-FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV2() (gas: 16306)
+FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV2() (gas: 16328)
FeeQuoter_resolveGasLimitForDestination:test_EVMExtraArgsV2TagSelector() (gas: 3168)
FeeQuoter_supportsInterface:test_SupportsInterface() (gas: 13264)
-FeeQuoter_updatePrices:test_OnlyGasPrice() (gas: 24001)
-FeeQuoter_updatePrices:test_OnlyTokenPrice() (gas: 28739)
-FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller() (gas: 74733)
-FeeQuoter_updatePrices:test_UpdateMultiplePrices() (gas: 146225)
+FeeQuoter_updatePrices:test_OnlyGasPrice() (gas: 23934)
+FeeQuoter_updatePrices:test_OnlyTokenPrice() (gas: 28761)
+FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller() (gas: 74821)
+FeeQuoter_updatePrices:test_UpdateMultiplePrices() (gas: 145980)
FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52495)
FeeQuoter_updateTokenPriceFeeds:test_FeedUnset() (gas: 66418)
FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate() (gas: 93559)
FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate() (gas: 53171)
FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds() (gas: 12471)
-FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6796)
-FeeQuoter_validateDestFamilyAddress:test_ValidSVMAddress() (gas: 6657)
+FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6818)
+FeeQuoter_validateDestFamilyAddress:test_ValidSVMAddress() (gas: 6679)
HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism() (gas: 130339)
HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism() (gas: 140169)
HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 202967)
@@ -203,20 +201,20 @@ NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123617)
NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed() (gas: 45935)
NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66937)
NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12123)
-NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 179167)
-NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 146356)
-NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 182637)
-NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 245611)
-NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 214256)
+NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 183777)
+NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 150965)
+NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 187248)
+NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 254856)
+NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 218870)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() (gas: 60418)
NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas: 37974)
NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38746)
NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce_SkippedIncorrectNonce() (gas: 23739)
NonceManager_getIncrementedOutboundNonce:test_incrementNoncesInboundAndOutbound() (gas: 71886)
-NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105901)
-NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 168082)
-NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 198449)
-NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 146148)
+NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105945)
+NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 168148)
+NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 198559)
+NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 146214)
OffRampWithMessageTransformer_executeSingleReport:test_executeSingleReport() (gas: 307118)
OffRampWithMessageTransformer_setMessageTransformer:test_setMessageTransformer() (gas: 701222)
OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains() (gas: 626140)
@@ -225,96 +223,96 @@ OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates() (gas: 16671)
OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain() (gas: 180998)
OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp() (gas: 168513)
OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed() (gas: 284861)
-OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 326824)
-OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 171115)
-OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 270123)
-OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 162336)
-OffRamp_batchExecute:test_SingleReport() (gas: 149878)
-OffRamp_batchExecute:test_Unhealthy() (gas: 533860)
-OffRamp_commit:test_OnlyGasPriceUpdates() (gas: 112973)
-OffRamp_commit:test_OnlyTokenPriceUpdates() (gas: 112927)
-OffRamp_commit:test_PriceSequenceNumberCleared() (gas: 355361)
-OffRamp_commit:test_ReportAndPriceUpdate() (gas: 164209)
+OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 340742)
+OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 175741)
+OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 284041)
+OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 166949)
+OffRamp_batchExecute:test_SingleReport() (gas: 154488)
+OffRamp_batchExecute:test_Unhealthy() (gas: 546735)
+OffRamp_commit:test_OnlyGasPriceUpdates() (gas: 112995)
+OffRamp_commit:test_OnlyTokenPriceUpdates() (gas: 112949)
+OffRamp_commit:test_PriceSequenceNumberCleared() (gas: 355405)
+OffRamp_commit:test_ReportAndPriceUpdate() (gas: 164231)
OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141051)
OffRamp_commit:test_RootWithRMNDisabled() (gas: 153873)
OffRamp_commit:test_StaleReportWithRoot() (gas: 232057)
-OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot() (gas: 206700)
+OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot() (gas: 206722)
OffRamp_constructor:test_Constructor() (gas: 6340113)
-OffRamp_execute:test_LargeBatch() (gas: 3383493)
-OffRamp_execute:test_MultipleReports() (gas: 292253)
-OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 365622)
-OffRamp_execute:test_SingleReport() (gas: 169111)
-OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 51610)
+OffRamp_execute:test_LargeBatch() (gas: 3537781)
+OffRamp_execute:test_MultipleReports() (gas: 306193)
+OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 370270)
+OffRamp_execute:test_SingleReport() (gas: 173724)
+OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 55443)
OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20514)
OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 230418)
-OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 87465)
-OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 259935)
-OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 455918)
-OffRamp_executeSingleReport:test_ReceiverError() (gas: 181083)
-OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 205792)
-OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 241879)
-OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 185785)
+OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91298)
+OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 265210)
+OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 462329)
+OffRamp_executeSingleReport:test_ReceiverError() (gas: 181094)
+OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 215033)
+OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 249545)
+OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 195030)
OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver() (gas: 244181)
-OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 134917)
+OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 139526)
OffRamp_executeSingleReport:test_SkippedIncorrectNonce() (gas: 58558)
-OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 392884)
-OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 562962)
-OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 511342)
-OffRamp_executeSingleReport:test_Unhealthy() (gas: 529483)
-OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 439833)
-OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 158559)
-OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 128943)
+OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 399284)
+OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 575811)
+OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 524188)
+OffRamp_executeSingleReport:test_Unhealthy() (gas: 542355)
+OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 450383)
+OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 163171)
+OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 133556)
OffRamp_getExecutionState:test_FillExecutionState() (gas: 3955662)
OffRamp_getExecutionState:test_GetDifferentChainExecutionState() (gas: 121311)
OffRamp_getExecutionState:test_GetExecutionState() (gas: 90102)
-OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212915)
-OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 166028)
+OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212742)
+OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 166042)
OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit() (gas: 479692)
OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2230185)
-OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 213465)
-OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 735042)
-OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 338095)
+OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 213292)
+OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 753781)
+OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 347264)
OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken() (gas: 94629)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 161157)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 163023)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 174276)
OffRamp_setDynamicConfig:test_SetDynamicConfig() (gas: 25442)
OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor() (gas: 47493)
-OffRamp_trialExecute:test_trialExecute() (gas: 263680)
+OffRamp_trialExecute:test_trialExecute() (gas: 268955)
OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 120710)
OffRamp_trialExecute:test_trialExecute_RevertsWhen_SenderIsGasEstimator_InsufficientGasForToCompleteTx() (gas: 67132)
OffRamp_trialExecute:test_trialExecute_SenderIsNotGasEstimator_CallWithExactGasReverts() (gas: 24573)
OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 131998)
-OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 281305)
-OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 245406)
-OnRampWithMessageTransformer_executeSingleMessage:test_forwardFromRouter() (gas: 122433)
+OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 286580)
+OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 245211)
+OnRampWithMessageTransformer_executeSingleMessage:test_forwardFromRouter() (gas: 122477)
OnRampWithMessageTransformer_setMessageTransformer:test_setMessageTransformer() (gas: 701204)
OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates() (gas: 325996)
OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17190)
OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates() (gas: 65874)
OnRamp_constructor:test_Constructor() (gas: 2694309)
-OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 146031)
-OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146843)
-OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 116022)
-OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 146429)
-OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144685)
-OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146670)
-OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 144010)
-OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 188414)
-OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 214791)
-OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147676)
-OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 275354)
-OnRamp_getFee:test_EmptyMessage() (gas: 100389)
-OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 89392)
-OnRamp_getFee:test_SingleTokenMessage() (gas: 115707)
+OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 146075)
+OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146887)
+OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 116066)
+OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 146473)
+OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144729)
+OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146714)
+OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 144032)
+OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 188546)
+OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 214923)
+OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147720)
+OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 275420)
+OnRamp_getFee:test_EmptyMessage() (gas: 100129)
+OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 89370)
+OnRamp_getFee:test_SingleTokenMessage() (gas: 115447)
OnRamp_getTokenPool:test_GetTokenPool() (gas: 35404)
OnRamp_setDynamicConfig:test_setDynamicConfig() (gas: 56650)
OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens() (gas: 125835)
-PingPong_ccipReceive:test_CcipReceive() (gas: 167519)
+PingPong_ccipReceive:test_CcipReceive() (gas: 167476)
PingPong_setOutOfOrderExecution:test_OutOfOrderExecution() (gas: 20284)
PingPong_setPaused:test_Pausing() (gas: 17760)
-PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 146670)
-PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 172301)
+PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 146627)
+PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 172258)
RMNHome_getConfigDigests:test_getConfigDigests() (gas: 1081176)
RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive() (gas: 1086556)
RMNHome_revokeCandidate:test_revokeCandidate() (gas: 28085)
@@ -342,42 +340,42 @@ RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig() (gas: 38645)
RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin() (gas: 130641)
RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin() (gas: 130136)
RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 129941)
-Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10413055)
+Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10864375)
Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56445)
-Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 126133)
-Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 213558)
+Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 126090)
+Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 213515)
Router_ccipSend:test_InvalidMsgValue() (gas: 27856)
-Router_ccipSend:test_NativeFeeToken() (gas: 186974)
-Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62761)
-Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 188369)
-Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54853)
-Router_ccipSend:test_NonLinkFeeToken() (gas: 221214)
-Router_ccipSend:test_WrappedNativeFeeToken() (gas: 189191)
-Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 135291)
-Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 222759)
+Router_ccipSend:test_NativeFeeToken() (gas: 186866)
+Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62696)
+Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 188261)
+Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54788)
+Router_ccipSend:test_NonLinkFeeToken() (gas: 221193)
+Router_ccipSend:test_WrappedNativeFeeToken() (gas: 189083)
+Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 135248)
+Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 222716)
Router_constructor:test_Constructor() (gas: 13170)
Router_getArmProxy:test_getArmProxy() (gas: 10573)
-Router_getFee:test_GetFeeSupportedChain() (gas: 52432)
+Router_getFee:test_GetFeeSupportedChain() (gas: 52367)
Router_recoverTokens:test_RecoverTokens() (gas: 52686)
-Router_routeMessage:test_routeMessage_AutoExec() (gas: 38071)
-Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 153593)
-Router_routeMessage:test_routeMessage_ManualExec() (gas: 31120)
+Router_routeMessage:test_routeMessage_AutoExec() (gas: 41832)
+Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 157232)
+Router_routeMessage:test_routeMessage_ManualExec() (gas: 34881)
SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_SiloedFunds() (gas: 76874)
SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_UnsiloedFunds() (gas: 76104)
-SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_LegacyProvideLiquiditySelector() (gas: 91873)
-SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_SiloedChain() (gas: 82416)
-SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_UnsiloedChain() (gas: 84036)
-SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_SiloedChain() (gas: 110002)
-SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_UnsiloedChain() (gas: 115718)
-SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_SiloedChain() (gas: 262340)
-SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_UnsiloedChain() (gas: 263392)
-SiloedLockReleaseTokenPool_setRebalancer:test_setRebalancer_UnsiloedChains() (gas: 24429)
-SiloedLockReleaseTokenPool_setRebalancer:test_setSiloRebalancer() (gas: 32165)
-SiloedLockReleaseTokenPool_updateSiloDesignations:test_updateSiloDesignations() (gas: 105825)
-SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_RevertsWhen_LegacyFunctionSelectorUnauthorized() (gas: 18244)
-SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_SiloedFunds() (gas: 70948)
-SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_UnsiloedFunds_LegacyFunctionSelector() (gas: 76391)
-SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawSiloedLiquidity_UnsiloedFunds() (gas: 71945)
+SiloedLockReleaseTokenPool_provideLiquidity:test_provideLiquidity() (gas: 89627)
+SiloedLockReleaseTokenPool_provideSiloedLiquidity:test_SiloedChain() (gas: 82328)
+SiloedLockReleaseTokenPool_provideSiloedLiquidity:test_UnsiloedChain() (gas: 81889)
+SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_SiloedChain() (gas: 109975)
+SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_RevertsWhen_InsufficientLiquidity_UnsiloedChain() (gas: 113535)
+SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_SiloedChain() (gas: 262243)
+SiloedLockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_UnsiloedChain() (gas: 263296)
+SiloedLockReleaseTokenPool_setRebalancer:test_setRebalancer_UnsiloedChains() (gas: 23661)
+SiloedLockReleaseTokenPool_setRebalancer:test_setSiloRebalancer() (gas: 27540)
+SiloedLockReleaseTokenPool_updateSiloDesignations:test_updateSiloDesignations() (gas: 135167)
+SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_RevertsWhen_LegacyFunctionSelectorUnauthorized() (gas: 16067)
+SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_SiloedFunds() (gas: 70845)
+SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawLiquidity_UnsiloedFunds_LegacyFunctionSelector() (gas: 72904)
+SiloedLockReleaseTokenPool_withdrawLiqudity:test_withdrawSiloedLiquidity_UnsiloedFunds() (gas: 70058)
TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole() (gas: 44236)
TokenAdminRegistry_addRegistryModule:test_addRegistryModule() (gas: 67093)
TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds() (gas: 11363)
diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts
index 4a3935475c5..5df1fc2bd76 100644
--- a/contracts/hardhat.config.ts
+++ b/contracts/hardhat.config.ts
@@ -132,7 +132,7 @@ let config = {
version: '0.8.19',
settings: COMPILER_SETTINGS,
},
- 'src/v0.8/workflow/dev/WorkflowRegistry.sol': {
+ 'src/v0.8/workflow/WorkflowRegistry.sol': {
version: '0.8.24',
settings: {
optimizer: {
diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation
index eb4b39201ba..32a7b2d60eb 100755
--- a/contracts/scripts/native_solc_compile_all_automation
+++ b/contracts/scripts/native_solc_compile_all_automation
@@ -108,4 +108,3 @@ compileContract automation/v2_3/AutomationUtils2_3.sol
compileContract automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol
compileContract automation/testhelpers/MockETHUSDAggregator.sol
-compileContract automation/test/WETH9.sol
diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip
index 91ce5ef8729..b6c94ea883c 100755
--- a/contracts/scripts/native_solc_compile_all_ccip
+++ b/contracts/scripts/native_solc_compile_all_ccip
@@ -73,8 +73,10 @@ compileContract pools/LockReleaseTokenPool
compileContract pools/BurnMintTokenPool
compileContract pools/BurnFromMintTokenPool
compileContract pools/BurnWithFromMintTokenPool
+compileContract pools/BurnToAddressMintTokenPool
compileContract pools/TokenPool
compileContract pools/USDC/USDCTokenPool
+compileContract pools/SiloedLockReleaseTokenPool
# Test helpers
compileContract test/helpers/BurnMintERC677Helper
@@ -86,7 +88,6 @@ compileContract test/helpers/receivers/LogMessageDataReceiver
compileContract test/helpers/MultiOCR3Helper
compileContract test/mocks/MockE2EUSDCTokenMessenger
compileContract test/mocks/MockE2EUSDCTransmitter
-compileContract test/WETH9
compileContract test/helpers/CCIPReaderTester
# Offchain test encoding utils
compileContract test/helpers/EncodingUtils
diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared
index 1b251db7d9b..97510629c0a 100755
--- a/contracts/scripts/native_solc_compile_all_shared
+++ b/contracts/scripts/native_solc_compile_all_shared
@@ -47,3 +47,4 @@ compileContract mocks/WERC20Mock
compileContract openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20 vendor
compileContract multicall/ebd8b64/src/Multicall3 vendor
+compileContract canonical-weth/WETH9 vendor
diff --git a/contracts/scripts/native_solc_compile_all_workflow b/contracts/scripts/native_solc_compile_all_workflow
index 5354eb29212..61411c63a86 100755
--- a/contracts/scripts/native_solc_compile_all_workflow
+++ b/contracts/scripts/native_solc_compile_all_workflow
@@ -29,4 +29,4 @@ compileContract () {
"$ROOT"/contracts/src/v0.8/"$1"
}
-compileContract workflow/dev/WorkflowRegistry.sol
+compileContract workflow/WorkflowRegistry.sol
diff --git a/contracts/src/v0.8/automation/test/WETH9.sol b/contracts/src/v0.8/automation/test/WETH9.sol
deleted file mode 100644
index 1225e6e39a8..00000000000
--- a/contracts/src/v0.8/automation/test/WETH9.sol
+++ /dev/null
@@ -1,93 +0,0 @@
-// Submitted for verification at Etherscan.io on 2017-12-12
-
-// Copyright (C) 2015, 2016, 2017 Dapphub
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-pragma solidity 0.8.19;
-
-contract WETH9 {
- string public name = "Wrapped Ether";
- string public symbol = "WETH";
- uint8 public decimals = 18;
-
- event Approval(address indexed src, address indexed guy, uint256 wad);
- event Transfer(address indexed src, address indexed dst, uint256 wad);
- event Deposit(address indexed dst, uint256 wad);
- event Withdrawal(address indexed src, uint256 wad);
-
- error InsufficientBalance();
-
- mapping(address => uint256) public balanceOf;
- mapping(address => mapping(address => uint256)) public allowance;
-
- receive() external payable {
- _deposit();
- }
-
- function _deposit() internal {
- balanceOf[msg.sender] += msg.value;
- emit Deposit(msg.sender, msg.value);
- }
-
- function deposit() external payable {
- _deposit();
- }
-
- function mint(address account, uint256 amount) public {
- balanceOf[account] += amount;
- }
-
- function withdraw(uint256 wad) external {
- if (balanceOf[msg.sender] < wad) {
- revert InsufficientBalance();
- }
- balanceOf[msg.sender] -= wad;
- payable(msg.sender).call{value: wad}("");
- emit Withdrawal(msg.sender, wad);
- }
-
- function totalSupply() public view returns (uint256) {
- return address(this).balance;
- }
-
- function approve(address guy, uint256 wad) public returns (bool) {
- allowance[msg.sender][guy] = wad;
- emit Approval(msg.sender, guy, wad);
- return true;
- }
-
- function transfer(address dst, uint256 wad) public returns (bool) {
- return transferFrom(msg.sender, dst, wad);
- }
-
- function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
- if (balanceOf[src] < wad) {
- revert InsufficientBalance();
- }
-
- if (src != msg.sender && allowance[src][msg.sender] != type(uint128).max) {
- if (allowance[src][msg.sender] < wad) {
- revert InsufficientBalance();
- }
- allowance[src][msg.sender] -= wad;
- }
-
- balanceOf[src] -= wad;
- balanceOf[dst] += wad;
-
- emit Transfer(src, dst, wad);
-
- return true;
- }
-}
diff --git a/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol
index 44bb0f0ae60..8e3f9760463 100644
--- a/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol
+++ b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol
@@ -4,7 +4,6 @@ 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 "../../../shared/mocks/MockV3Aggregator.sol";
import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol";
@@ -17,10 +16,12 @@ import {AutomationRegistryLogicC2_3} from "../../v2_3/AutomationRegistryLogicC2_
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 {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
+import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol";
+import {WETH9} from "../../../vendor/canonical-weth/WETH9.sol";
/**
* @title BaseTest provides basic test setup procedures and dependencies for use by other
@@ -137,10 +138,10 @@ contract BaseTest is Test {
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);
+ deal(address(weth), OWNER, 100 ether);
+ deal(address(weth), UPKEEP_ADMIN, 100 ether);
+ deal(address(weth), FINANCE_ADMIN, 100 ether);
+ deal(address(weth), STRANGER, 100 ether);
vm.stopPrank();
}
diff --git a/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol b/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol
index f33360aa9f6..0b534ef3575 100644
--- a/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol
+++ b/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol
@@ -4,7 +4,6 @@ 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 "../../../shared/mocks/MockV3Aggregator.sol";
import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol";
@@ -17,13 +16,15 @@ import {ZKSyncAutomationRegistryBase2_3 as ZKSyncAutoBase} from "../../v2_3_zksy
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 "../../mocks/MockGasBoundCaller.sol";
import {MockZKSyncSystemContext} from "../../mocks/MockZKSyncSystemContext.sol";
+import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol";
+import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol";
+import {WETH9} from "../../../vendor/canonical-weth/WETH9.sol";
+
/**
* @title BaseTest provides basic test setup procedures and dependencies for use by other
* unit tests
@@ -149,10 +150,10 @@ contract BaseTest is Test {
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);
+ deal(address(weth), OWNER, 100 ether);
+ deal(address(weth), UPKEEP_ADMIN, 100 ether);
+ deal(address(weth), FINANCE_ADMIN, 100 ether);
+ deal(address(weth), STRANGER, 100 ether);
vm.stopPrank();
}
diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol
index 590233c6230..699edeefbea 100644
--- a/contracts/src/v0.8/ccip/FeeQuoter.sol
+++ b/contracts/src/v0.8/ccip/FeeQuoter.sol
@@ -555,12 +555,13 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver,
Client.EVM2AnyMessage calldata message
) external view returns (uint256 feeTokenAmount) {
DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector];
+ if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector);
if (!s_feeTokens.contains(message.feeToken)) revert FeeTokenNotSupported(message.feeToken);
uint256 numberOfTokens = message.tokenAmounts.length;
- uint256 gasLimit = _resolveGasLimitForDestination(message.extraArgs, destChainConfig);
-
- _validateMessage(destChainConfig, message.data.length, numberOfTokens, gasLimit, message.receiver);
+ uint256 gasLimit = _validateMessageAndResolveGasLimitForDestination(
+ destChainConfig, message.data.length, numberOfTokens, message.extraArgs, message.receiver
+ );
// The below call asserts that feeToken is a supported token.
uint224 feeTokenPrice = _getValidatedTokenPrice(message.feeToken);
@@ -890,44 +891,24 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver,
revert InvalidChainFamilySelector(chainFamilySelector);
}
- function _resolveGasLimitForDestination(
- bytes calldata extraArgs,
- DestChainConfig memory destChainConfig
- ) internal pure returns (uint256) {
- if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) {
- return _parseEVMExtraArgsFromBytes(
- extraArgs,
- destChainConfig.defaultTxGasLimit,
- destChainConfig.maxPerMsgGasLimit,
- destChainConfig.enforceOutOfOrder
- ).gasLimit;
- }
- if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SVM) {
- return _parseSVMExtraArgsFromBytes(
- extraArgs, destChainConfig.maxPerMsgGasLimit, destChainConfig.enforceOutOfOrder
- ).computeUnits;
- }
- revert InvalidChainFamilySelector(destChainConfig.chainFamilySelector);
- }
-
/// @notice Parse and validate the SVM specific Extra Args Bytes.
function _parseSVMExtraArgsFromBytes(
bytes calldata extraArgs,
uint256 maxPerMsgGasLimit,
- bool enforcedOutOfOrder
+ bool enforceOutOfOrder
) internal pure returns (Client.SVMExtraArgsV1 memory svmExtraArgs) {
if (extraArgs.length == 0) {
revert InvalidExtraArgsData();
}
bytes4 tag = bytes4(extraArgs[:4]);
- if (tag != Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG) {
+ if (tag != Client.SVM_EXTRA_ARGS_V1_TAG) {
revert InvalidExtraArgsTag();
}
svmExtraArgs = abi.decode(extraArgs[4:], (Client.SVMExtraArgsV1));
- if (enforcedOutOfOrder && !svmExtraArgs.allowOutOfOrderExecution) {
+ if (enforceOutOfOrder && !svmExtraArgs.allowOutOfOrderExecution) {
revert ExtraArgOutOfOrderExecutionMustBeTrue();
}
@@ -993,13 +974,14 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver,
/// @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.
- function _validateMessage(
+ /// @return gasLimit The gas limit to use for the message.
+ function _validateMessageAndResolveGasLimitForDestination(
DestChainConfig memory destChainConfig,
uint256 dataLength,
uint256 numberOfTokens,
- uint256 gasLimit,
+ bytes calldata extraArgs,
bytes memory receiver
- ) internal pure {
+ ) internal pure returns (uint256 gasLimit) {
// Check that payload is formed correctly.
if (dataLength > uint256(destChainConfig.maxDataBytes)) {
revert MessageTooLarge(uint256(destChainConfig.maxDataBytes), dataLength);
@@ -1007,7 +989,29 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver,
if (numberOfTokens > uint256(destChainConfig.maxNumberOfTokensPerMsg)) {
revert UnsupportedNumberOfTokens(numberOfTokens, destChainConfig.maxNumberOfTokensPerMsg);
}
+
+ // resolve gas limit and validate chainFamilySelector
+ if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) {
+ gasLimit = _parseEVMExtraArgsFromBytes(
+ extraArgs,
+ destChainConfig.defaultTxGasLimit,
+ destChainConfig.maxPerMsgGasLimit,
+ destChainConfig.enforceOutOfOrder
+ ).gasLimit;
+ } else if (destChainConfig.chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_SVM) {
+ Client.SVMExtraArgsV1 memory svmExtraArgsV1 =
+ _parseSVMExtraArgsFromBytes(extraArgs, destChainConfig.maxPerMsgGasLimit, destChainConfig.enforceOutOfOrder);
+ if (numberOfTokens > 0 && svmExtraArgsV1.tokenReceiver == bytes32(0)) {
+ revert InvalidTokenReceiver();
+ }
+ gasLimit = svmExtraArgsV1.computeUnits;
+ } else {
+ revert InvalidChainFamilySelector(destChainConfig.chainFamilySelector);
+ }
+
_validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver, gasLimit);
+
+ return gasLimit;
}
/// @inheritdoc IFeeQuoter
@@ -1150,9 +1154,14 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver,
DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig;
// destChainSelector must be non-zero, defaultTxGasLimit must be set, must be less than maxPerMsgGasLimit
+ // supported chain family is EVM and SVM
if (
destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0
|| destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit
+ || (
+ destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM
+ && destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_SVM
+ )
) {
revert InvalidDestChainConfig(destChainSelector);
}
diff --git a/contracts/src/v0.8/ccip/libraries/Client.sol b/contracts/src/v0.8/ccip/libraries/Client.sol
index cde66e46cc0..a3b89fdc59f 100644
--- a/contracts/src/v0.8/ccip/libraries/Client.sol
+++ b/contracts/src/v0.8/ccip/libraries/Client.sol
@@ -43,7 +43,7 @@ library Client {
bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10;
// bytes4(keccak256("CCIP SVMExtraArgsV1"));
- bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba;
+ bytes4 public constant SVM_EXTRA_ARGS_V1_TAG = 0x1f3b3aba;
/// @param gasLimit: gas limit for the callback on the destination chain.
/// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to
@@ -71,6 +71,6 @@ library Client {
function _svmArgsToBytes(
SVMExtraArgsV1 memory extraArgs
) internal pure returns (bytes memory bts) {
- return abi.encodeWithSelector(SVM_EXTRA_EXTRA_ARGS_V1_TAG, extraArgs);
+ return abi.encodeWithSelector(SVM_EXTRA_ARGS_V1_TAG, extraArgs);
}
}
diff --git a/contracts/src/v0.8/ccip/offRamp/OffRampWithMessageTransformer.sol b/contracts/src/v0.8/ccip/offRamp/OffRampWithMessageTransformer.sol
index a2067fbbbdf..2e86d77e496 100644
--- a/contracts/src/v0.8/ccip/offRamp/OffRampWithMessageTransformer.sol
+++ b/contracts/src/v0.8/ccip/offRamp/OffRampWithMessageTransformer.sol
@@ -16,7 +16,7 @@ contract OffRampWithMessageTransformer is OffRamp {
SourceChainConfigArgs[] memory sourceChainConfigs,
address messageTransformerAddr
) OffRamp(staticConfig, dynamicConfig, sourceChainConfigs) {
- if (address(messageTransformerAddr) == address(0)) {
+ if (messageTransformerAddr == address(0)) {
revert ZeroAddressNotAllowed();
}
s_messageTransformer = messageTransformerAddr;
@@ -33,7 +33,7 @@ contract OffRampWithMessageTransformer is OffRamp {
function setMessageTransformer(
address messageTransformerAddr
) external onlyOwner {
- if (address(messageTransformerAddr) == address(0)) {
+ if (messageTransformerAddr == address(0)) {
revert ZeroAddressNotAllowed();
}
s_messageTransformer = messageTransformerAddr;
diff --git a/contracts/src/v0.8/ccip/onRamp/OnRampWithMessageTransformer.sol b/contracts/src/v0.8/ccip/onRamp/OnRampWithMessageTransformer.sol
index f7800bb062a..cd21b47e148 100644
--- a/contracts/src/v0.8/ccip/onRamp/OnRampWithMessageTransformer.sol
+++ b/contracts/src/v0.8/ccip/onRamp/OnRampWithMessageTransformer.sol
@@ -18,7 +18,7 @@ contract OnRampWithMessageTransformer is OnRamp {
DestChainConfigArgs[] memory destChainConfigs,
address messageTransformerAddr
) OnRamp(staticConfig, dynamicConfig, destChainConfigs) {
- if (address(messageTransformerAddr) == address(0)) {
+ if (messageTransformerAddr == address(0)) {
revert ZeroAddressNotAllowed();
}
s_messageTransformer = messageTransformerAddr;
@@ -35,7 +35,7 @@ contract OnRampWithMessageTransformer is OnRamp {
function setMessageTransformer(
address messageTransformerAddr
) external onlyOwner {
- if (address(messageTransformerAddr) == address(0)) {
+ if (messageTransformerAddr == address(0)) {
revert ZeroAddressNotAllowed();
}
s_messageTransformer = messageTransformerAddr;
diff --git a/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol
index 563375f099a..b32dfed183b 100644
--- a/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol
+++ b/contracts/src/v0.8/ccip/pools/BurnToAddressMintTokenPool.sol
@@ -4,7 +4,6 @@ pragma solidity ^0.8.24;
import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";
import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol";
-import {Pool} from "../libraries/Pool.sol";
import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol";
import {TokenPool} from "./TokenPool.sol";
@@ -18,10 +17,6 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok
contract BurnToAddressMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion {
using SafeERC20 for IERC20;
- event OutstandingTokensSet(uint256 newMintedTokenAmount, uint256 oldMintedTokenAmount);
-
- error InsufficientOutstandingTokens();
-
string public constant override typeAndVersion = "BurnToAddressTokenPool 1.5.1";
/// @notice The address where tokens are sent during a call to lockOrBurn, functionally burning but without decreasing
@@ -29,12 +24,6 @@ contract BurnToAddressMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersio
/// This can be either an EOA without a corresponding private key, or a contract which does not have the ability to transfer the tokens.
address public immutable i_burnAddress;
- /// @notice Minted Tokens is a safety mechanism to ensure that more tokens cannot be sent out of the bridge
- /// than were originally sent in via CCIP. On incoming messages the value is increased, and on outgoing messages,
- /// the value is decreased. For pools with existing tokens in circulation, the value may not be known at deployment
- /// time, and thus should be set later using the setoutstandingTokens() function.
- uint256 internal s_outstandingTokens;
-
/// @dev Since burnAddress is expected to make the tokens unrecoverable, no check for the zero address needs to be
/// performed, as it is a valid input.
constructor(
@@ -48,32 +37,12 @@ contract BurnToAddressMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersio
i_burnAddress = burnAddress;
}
- /// @notice Mint tokens from the pool to the recipient, updating the internal accounting for an outflow of tokens.
- /// @dev If the amount of tokens to be
- function releaseOrMint(
- Pool.ReleaseOrMintInV1 calldata releaseOrMintIn
- ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) {
- // When minting tokens, the local outstanding supply increases. These tokens will be burned
- // when they are sent back to the pool on an outgoing message.
- s_outstandingTokens += releaseOrMintIn.amount;
-
- return super.releaseOrMint(releaseOrMintIn);
- }
-
/// @inheritdoc BurnMintTokenPoolAbstract
/// @notice Tokens are burned by sending to an address which can never transfer them,
/// making the tokens unrecoverable without reducing the total supply.
function _burn(
uint256 amount
) internal virtual override {
- if (amount > s_outstandingTokens) {
- revert InsufficientOutstandingTokens();
- }
-
- // When tokens are burned, the amount outstanding decreases. This ensures that more tokens cannot be sent out
- // of the bridge than were originally sent in via CCIP.
- s_outstandingTokens -= amount;
-
getToken().safeTransfer(i_burnAddress, amount);
}
@@ -82,22 +51,4 @@ contract BurnToAddressMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersio
function getBurnAddress() public view returns (address burnAddress) {
return i_burnAddress;
}
-
- /// @notice Return the amount of tokens which were minted by this contract and not yet burned.
- /// @return outstandingTokens The amount of tokens which were minted by this token pool and not yet burned.
- function getOutstandingTokens() public view returns (uint256 outstandingTokens) {
- return s_outstandingTokens;
- }
-
- /// @notice Set the amount of tokens which were minted by this contract and not yet burned.
- /// @param amount The new amount of tokens which were minted by this token pool and not yet burned.
- function setOutstandingTokens(
- uint256 amount
- ) external onlyOwner {
- uint256 currentOutstandingTokens = s_outstandingTokens;
-
- s_outstandingTokens = amount;
-
- emit OutstandingTokensSet(amount, currentOutstandingTokens);
- }
}
diff --git a/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol
index adb3a452957..0571e427860 100644
--- a/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol
+++ b/contracts/src/v0.8/ccip/pools/SiloedLockReleaseTokenPool.sol
@@ -17,9 +17,10 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
error InsufficientLiquidity(uint256 availableLiquidity, uint256 requestedAmount);
error ChainNotSiloed(uint64 remoteChainSelector);
error InvalidChainSelector(uint64 remoteChainSelector);
+ error LiquidityAmountCannotBeZero();
event LiquidityAdded(uint64 remoteChainSelector, address indexed provider, uint256 amount);
- event LiquidityRemoved(uint64 remoteChainSelector, address indexed provider, uint256 amount);
+ event LiquidityRemoved(uint64 remoteChainSelector, address indexed remover, uint256 amount);
event ChainUnsiloed(uint64 remoteChainSelector, uint256 amountUnsiloed);
event ChainSiloed(uint64 remoteChainSelector, address rebalancer);
event SiloRebalancerSet(uint64 indexed remoteChainSelector, address oldRebalancer, address newRebalancer);
@@ -95,13 +96,16 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
// Save gas by using storage instead of memory as a value may need to be updated.
SiloConfig storage remoteConfig = s_chainConfigs[releaseOrMintIn.remoteChainSelector];
+ // Since remoteConfig.isSiloed is used more than once, caching in memory saves gas instead of multiple SLOADs.
+ bool isSiloed = remoteConfig.isSiloed;
+
// Prevent A silent underflow by explicitly ensuring that enough funds are available to release
- uint256 availableLiquidity = remoteConfig.isSiloed ? remoteConfig.tokenBalance : s_unsiloedTokenBalance;
+ uint256 availableLiquidity = isSiloed ? remoteConfig.tokenBalance : s_unsiloedTokenBalance;
if (localAmount > availableLiquidity) revert InsufficientLiquidity(availableLiquidity, localAmount);
// Tracking balances independently by chain is a security measure to prevent liquidity for one chain from being
// released by another chain.
- if (remoteConfig.isSiloed) {
+ if (isSiloed) {
remoteConfig.tokenBalance -= localAmount;
} else {
s_unsiloedTokenBalance -= localAmount;
@@ -115,16 +119,6 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount});
}
- /// @notice Returns whether the tokens locked for a given remote chain should be siloed independently
- /// from all other remote chains.
- /// @param remoteChainSelector the CCIP specific selector for the remote chain being interacted with.
- /// @return isSiloed Whether the funds should be isolated from all the others.
- function isSiloed(
- uint64 remoteChainSelector
- ) external view returns (bool) {
- return s_chainConfigs[remoteChainSelector].isSiloed;
- }
-
/// @notice Returns the amount of tokens in the token pool that were siloed for a specific remote chain selector.
/// @param remoteChainSelector the CCIP specific selector for the remote chain being interacted with.
/// @return lockedTokens The tokens locked into this token pool for the given selector. If the chain is not siloed,
@@ -145,11 +139,24 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
return s_unsiloedTokenBalance;
}
+ // ================================================================
+ // │ Chain Management │
+ // ================================================================
+
+ /// @notice Returns whether the tokens locked for a given remote chain should be siloed independently
+ /// from all other remote chains.
+ /// @param remoteChainSelector the CCIP specific selector for the remote chain being interacted with.
+ /// @return isSiloed Whether the funds should be isolated from all the others.
+ function isSiloed(
+ uint64 remoteChainSelector
+ ) external view returns (bool) {
+ return s_chainConfigs[remoteChainSelector].isSiloed;
+ }
+
/// @notice Updates designations for chains on whether to mark funds as Siloed or not
/// @param removes A list of chain selectors to disable Siloing. Their funds will be moved into the unsiloed pool.
/// If a chain is not siloed, and attempted to be removed, the function will revert.
- /// @param adds A list of chain selectors to enable Siloing. Adding a chain to siloing will not set the rebalancer.
- /// The rebalancer will need to be set separately.
+ /// @param adds A list of chain selectors to enable Siloing.
function updateSiloDesignations(uint64[] calldata removes, SiloConfigUpdate[] calldata adds) external onlyOwner {
for (uint256 i = 0; i < removes.length; ++i) {
if (!s_chainConfigs[removes[i]].isSiloed) revert ChainNotSiloed(removes[i]);
@@ -167,13 +174,12 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
for (uint256 i = 0; i < adds.length; ++i) {
// Since the zero chain selector is used to designate unsiloed chains, it should never be used for siloed chains.
- if (adds[i].remoteChainSelector == 0) {
- revert InvalidChainSelector(0);
+ if (adds[i].remoteChainSelector == 0 || s_chainConfigs[adds[i].remoteChainSelector].isSiloed) {
+ revert InvalidChainSelector(adds[i].remoteChainSelector);
}
- SiloConfig memory newConfig = SiloConfig({tokenBalance: 0, rebalancer: adds[i].rebalancer, isSiloed: true});
-
- s_chainConfigs[adds[i].remoteChainSelector] = newConfig;
+ s_chainConfigs[adds[i].remoteChainSelector] =
+ SiloConfig({tokenBalance: 0, rebalancer: adds[i].rebalancer, isSiloed: true});
emit ChainSiloed(adds[i].remoteChainSelector, adds[i].rebalancer);
}
@@ -181,11 +187,11 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
/// @notice Gets the rebalancer able to provide liquidity for a remote chain selector
/// @param remoteChainSelector The CCIP specific selector for the remote chain being interacted with.
- /// @return The current liquidity manager, contract owner if the chain's funds are not siloed.
+ /// @return The current liquidity manager for the given siloed chain, or the unsiloed rebalancer if the chain is not siloed.
function getSiloRebalancer(
uint64 remoteChainSelector
) public view returns (address) {
- SiloConfig memory remoteConfig = s_chainConfigs[remoteChainSelector];
+ SiloConfig storage remoteConfig = s_chainConfigs[remoteChainSelector];
if (remoteConfig.isSiloed) {
return remoteConfig.rebalancer;
}
@@ -193,20 +199,26 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
return s_rebalancer;
}
+ /// @notice Gets the rebalancer for the unsiloed chains.
+ /// @return The current liquidity manager for the unsiloed chains.
+ function getRebalancer() external view returns (address) {
+ return s_rebalancer;
+ }
+
/// @notice Sets the Rebalancer address for a given remoteChainSelector.
/// @dev Only callable by the owner.
/// @param remoteChainSelector the remote chain to set.
/// @param newRebalancer the address allowed to add liquidity for the given siloed chain.
function setSiloRebalancer(uint64 remoteChainSelector, address newRebalancer) external onlyOwner {
- SiloConfig memory remoteConfig = s_chainConfigs[remoteChainSelector];
+ SiloConfig storage remoteConfig = s_chainConfigs[remoteChainSelector];
if (!remoteConfig.isSiloed) revert ChainNotSiloed(remoteChainSelector);
address oldRebalancer = remoteConfig.rebalancer;
- s_chainConfigs[remoteChainSelector].rebalancer = newRebalancer;
+ remoteConfig.rebalancer = newRebalancer;
- emit SiloRebalancerSet(remoteChainSelector, newRebalancer, oldRebalancer);
+ emit SiloRebalancerSet(remoteChainSelector, oldRebalancer, newRebalancer);
}
/// @notice Sets the Rebalancer address for unsiloed chains.
@@ -219,15 +231,20 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
s_rebalancer = newRebalancer;
- emit UnsiloedRebalancerSet(newRebalancer, oldRebalancer);
+ emit UnsiloedRebalancerSet(oldRebalancer, newRebalancer);
}
+ // ================================================================
+ // │ Provide Liquidity │
+ // ================================================================
+
/// @notice Adds liquidity to the pool. The tokens should be approved first.
/// @param remoteChainSelector the remote chain to set. If the chain is not siloed, the liquidity will be shared among all
/// non-siloed chains.
/// @param amount The amount of liquidity to provide.
/// @dev Only the rebalancer for the chain can add liquidity
function provideSiloedLiquidity(uint64 remoteChainSelector, uint256 amount) external {
+ if (remoteChainSelector == 0) revert InvalidChainSelector(0);
_provideLiquidity(remoteChainSelector, amount);
}
@@ -242,6 +259,7 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
}
function _provideLiquidity(uint64 remoteChainSelector, uint256 amount) internal {
+ if (amount == 0) revert LiquidityAmountCannotBeZero();
if (msg.sender != getSiloRebalancer(remoteChainSelector)) revert Unauthorized(msg.sender);
// Storage is used instead of memory to save gas, as the state may need to be updated if the chain is siloed.
@@ -257,6 +275,10 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
emit LiquidityAdded(remoteChainSelector, msg.sender, amount);
}
+ // ================================================================
+ // │ Withdraw Liquidity │
+ // ================================================================
+
/// @notice Removes liquidity from the pool for unsiloed chains. Function is used to support legacy liquidity operations
/// by using a function selector available to previous L/R pools.
/// @dev Since the remoteChainSelector 0 should never be applied to a real chain, it is used to designate unsiloed chains.
@@ -277,6 +299,7 @@ contract SiloedLockReleaseTokenPool is TokenPool, ITypeAndVersion {
}
function _withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) internal {
+ if (amount == 0) revert LiquidityAmountCannotBeZero();
if (msg.sender != getSiloRebalancer(remoteChainSelector)) revert Unauthorized(msg.sender);
// Save gas by using storage as multiple values may need to be read/written.
diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol
index 1d30a8f589f..776a1d452b9 100644
--- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol
+++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol
@@ -8,8 +8,8 @@ import {IRMNRemote} from "../interfaces/IRMNRemote.sol";
import {Router} from "../Router.sol";
import {Internal} from "../libraries/Internal.sol";
import {RateLimiter} from "../libraries/RateLimiter.sol";
-import {WETH9} from "./WETH9.sol";
+import {WETH9} from "../../vendor/canonical-weth/WETH9.sol";
import {Test} from "forge-std/Test.sol";
contract BaseTest is Test {
diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTestSetup.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTestSetup.t.sol
index b989a11b3ef..2cdf1526923 100644
--- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTestSetup.t.sol
+++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTestSetup.t.sol
@@ -5,9 +5,9 @@ import {Test} from "forge-std/Test.sol";
import {ICCIPRouter} from "../../../applications/EtherSenderReceiver.sol";
-import {WETH9} from "../../WETH9.sol";
import {EtherSenderReceiverHelper} from "../../helpers/EtherSenderReceiverHelper.sol";
+import {WETH9} from "../../../../vendor/canonical-weth/WETH9.sol";
import {ERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol";
contract EtherSenderReceiverTestSetup is Test {
diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol
index 242b513cf5a..703cade2c9f 100644
--- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol
+++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol
@@ -6,6 +6,9 @@ import {Internal} from "../../libraries/Internal.sol";
import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol";
contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup {
+ bytes4[] internal s_validChainFamilySelector =
+ [Internal.CHAIN_FAMILY_SELECTOR_EVM, Internal.CHAIN_FAMILY_SELECTOR_SVM];
+
function testFuzz_applyDestChainConfigUpdates_Success(
FeeQuoter.DestChainConfigArgs memory destChainConfigArgs
) public {
@@ -16,26 +19,25 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup {
destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit
)
);
- destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM;
- bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR;
+ for (uint256 i = 0; i < s_validChainFamilySelector.length; i++) {
+ destChainConfigArgs.destChainConfig.chainFamilySelector = s_validChainFamilySelector[i];
+ destChainConfigArgs.destChainSelector = uint64(
+ uint256(keccak256(abi.encodePacked(destChainConfigArgs.destChainSelector, s_validChainFamilySelector[i])))
+ );
- FeeQuoter.DestChainConfigArgs[] memory newDestChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1);
- newDestChainConfigArgs[0] = destChainConfigArgs;
+ 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);
+ s_feeQuoter.applyDestChainConfigUpdates(newDestChainConfigArgs);
- _assertFeeQuoterDestChainConfigsEqual(
- destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector)
- );
+ _assertFeeQuoterDestChainConfigsEqual(
+ destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector)
+ );
+ }
}
function test_applyDestChainConfigUpdates() public {
@@ -109,4 +111,16 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup {
);
s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs);
}
+
+ function test_RevertWhen_InvalidChainFamilySelector() public {
+ FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs();
+ FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0];
+
+ destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1));
+
+ vm.expectRevert(
+ abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector)
+ );
+ s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs);
+ }
}
diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol
index 67ff5ae4ede..fd1f7d3d255 100644
--- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol
+++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol
@@ -223,6 +223,11 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup {
// Reverts
+ function test_RevertWhen_DestinationChainNotEnabled() public {
+ vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1));
+ s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage());
+ }
+
function test_RevertWhen_EnforceOutOfOrder() public {
// Update config to enforce allowOutOfOrderExecution = true.
vm.stopPrank();
@@ -283,4 +288,30 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup {
s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message);
}
+
+ function test_RevertWhen_SVMMessageWithTokenTransferAndInvalidTokenReceiver() public {
+ vm.stopPrank();
+ //setup to set chainFamilySelector for SVM so that token receiver's check flow is enabled
+ vm.startPrank(OWNER);
+
+ FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs();
+ destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_SVM;
+
+ s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs);
+ vm.stopPrank();
+
+ Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1);
+ // replace with SVM Extra Args
+ message.extraArgs = Client._svmArgsToBytes(
+ Client.SVMExtraArgsV1({
+ computeUnits: GAS_LIMIT,
+ accountIsWritableBitmap: 0,
+ allowOutOfOrderExecution: true,
+ tokenReceiver: bytes32(0),
+ accounts: new bytes32[](0)
+ })
+ );
+ vm.expectRevert(FeeQuoter.InvalidTokenReceiver.selector);
+ s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message);
+ }
}
diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol
index 882fc17fe8f..8c56279aecf 100644
--- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol
+++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseSVMExtraArgsFromBytes.t.sol
@@ -27,7 +27,7 @@ contract FeeQuoter_parseSVMExtraArgsFromBytes is FeeQuoterSetup {
}
function test_SVMExtraArgsV1TagSelector() public view {
- assertEq(Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG, bytes4(keccak256("CCIP SVMExtraArgsV1")));
+ assertEq(Client.SVM_EXTRA_ARGS_V1_TAG, bytes4(keccak256("CCIP SVMExtraArgsV1")));
}
function test_SVMExtraArgsV1() public view {
@@ -89,12 +89,12 @@ contract FeeQuoter_parseSVMExtraArgsFromBytes is FeeQuoterSetup {
function test_RevertWhen_ExtraArgOutOfOrderExecutionIsFalse() public {
bytes memory inputExtraArgs = abi.encodeWithSelector(
- Client.SVM_EXTRA_EXTRA_ARGS_V1_TAG,
+ Client.SVM_EXTRA_ARGS_V1_TAG,
Client.SVMExtraArgsV1({
computeUnits: 1_000_000,
accountIsWritableBitmap: 0,
tokenReceiver: bytes32(0),
- allowOutOfOrderExecution: false, // mismatch with enforcedOutOfOrder = true
+ allowOutOfOrderExecution: false, // mismatch with enforceOutOfOrder = true
accounts: new bytes32[](0)
})
);
diff --git a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol
index 6e4233b7d1f..3dd711e7998 100644
--- a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol
+++ b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol
@@ -112,11 +112,4 @@ contract FeeQuoterHelper is FeeQuoter {
) external pure returns (uint224) {
return _calculateRebasedValue(dataFeedDecimal, tokenDecimal, feedValue);
}
-
- function resolveGasLimitForDestination(
- bytes calldata extraArgs,
- DestChainConfig memory destChainConfig
- ) external pure returns (uint256 gasLimit) {
- return _resolveGasLimitForDestination(extraArgs, destChainConfig);
- }
}
diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol
index 91a697ac318..8352a84853e 100644
--- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol
+++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol
@@ -1,29 +1,43 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
+import {IERC20} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol";
+import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";
import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol";
import {Client} from "../../../libraries/Client.sol";
-import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";
-
contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {
error ReceiveRevert();
error CustomError(bytes err);
+ error Unauthorized();
+ error InsufficientBalance(uint256 available, uint256 required);
+ error TransferFailed();
event ValueReceived(uint256 amount);
- event MessageReceived();
+ event NativeFundsWithdrawn(address indexed owner, uint256 amount);
+ event TokensWithdrawn(address indexed token, address indexed owner, uint256 amount);
+ event MessageReceived(
+ bytes32 messageId, uint64 sourceChainSelector, bytes sender, bytes data, Client.EVMTokenAmount[] destTokenAmounts
+ );
- address private s_manager;
+ address private immutable i_manager;
bool public s_toRevert;
bytes private s_err;
constructor(
bool toRevert
) {
- s_manager = msg.sender;
+ i_manager = msg.sender;
s_toRevert = toRevert;
}
+ modifier onlyManager() {
+ if (msg.sender != i_manager) {
+ revert Unauthorized();
+ }
+ _;
+ }
+
function setRevert(
bool toRevert
) external {
@@ -46,12 +60,15 @@ contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {
}
function ccipReceive(
- Client.Any2EVMMessage calldata
+ Client.Any2EVMMessage calldata message
) external override {
if (s_toRevert) {
revert CustomError(s_err);
}
- emit MessageReceived();
+
+ emit MessageReceived(
+ message.messageId, message.sourceChainSelector, message.sender, message.data, message.destTokenAmounts
+ );
}
// solhint-disable-next-line no-complex-fallback
@@ -62,4 +79,44 @@ contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {
emit ValueReceived(msg.value);
}
+
+ /// @notice Allows the manager (deployer) to withdraw all Ether from the contract
+ function withdrawFunds() external onlyManager {
+ uint256 balance = address(this).balance;
+
+ (bool success,) = i_manager.call{value: balance}("");
+ if (!success) {
+ revert TransferFailed();
+ }
+
+ emit NativeFundsWithdrawn(i_manager, balance);
+ }
+
+ /// @notice Allows the manager to withdraw ERC-20 tokens from the contract
+ /// @param token The address of the ERC-20 token contract
+ /// @param amount The amount of tokens to withdraw
+ function withdrawTokens(address token, uint256 amount) external onlyManager {
+ IERC20 erc20 = IERC20(token);
+ uint256 balance = erc20.balanceOf(address(this));
+ if (balance < amount) {
+ revert InsufficientBalance(balance, amount);
+ }
+
+ bool success = erc20.transfer(i_manager, amount);
+ if (!success) {
+ revert TransferFailed();
+ }
+
+ emit TokensWithdrawn(token, i_manager, amount);
+ }
+
+ /// @notice Fetches the balance of an ERC-20 token held by the contract
+ /// @param token The address of the ERC-20 token contract
+ /// @return The balance of the specified ERC-20 token
+ function balanceOfToken(
+ address token
+ ) external view returns (uint256) {
+ IERC20 erc20 = IERC20(token);
+ return erc20.balanceOf(address(this));
+ }
}
diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol
index c5e559b2d9e..454778f11c6 100644
--- a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol
+++ b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.lockOrBurn.t.sol
@@ -2,7 +2,6 @@
pragma solidity ^0.8.24;
import {Pool} from "../../../libraries/Pool.sol";
-import {BurnToAddressMintTokenPool} from "../../../pools/BurnToAddressMintTokenPool.sol";
import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol";
import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
@@ -11,8 +10,6 @@ contract BurnToAddressMintTokenPool_lockOrBurn is BurnToAddressMintTokenPoolSetu
uint256 public constant AMOUNT = 1e24;
function test_LockOrBurn() public {
- s_pool.setOutstandingTokens(AMOUNT);
-
deal(address(s_burnMintERC20), address(s_pool), AMOUNT);
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), AMOUNT);
@@ -35,29 +32,5 @@ contract BurnToAddressMintTokenPool_lockOrBurn is BurnToAddressMintTokenPoolSetu
assertEq(s_burnMintERC20.balanceOf(s_pool.getBurnAddress()), AMOUNT);
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0);
- assertEq(s_pool.getOutstandingTokens(), 0);
- }
-
- // Reverts
-
- function test_LockOrBurn_RevertWhen_InsufficientOutstandingTokens() public {
- s_pool.setOutstandingTokens(AMOUNT - 1);
-
- deal(address(s_burnMintERC20), address(s_pool), AMOUNT);
- assertEq(s_burnMintERC20.balanceOf(address(s_pool)), AMOUNT);
-
- vm.startPrank(s_burnMintOnRamp);
-
- vm.expectRevert(BurnToAddressMintTokenPool.InsufficientOutstandingTokens.selector);
-
- s_pool.lockOrBurn(
- Pool.LockOrBurnInV1({
- originalSender: OWNER,
- receiver: bytes(""),
- amount: AMOUNT,
- remoteChainSelector: DEST_CHAIN_SELECTOR,
- localToken: address(s_burnMintERC20)
- })
- );
}
}
diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol
deleted file mode 100644
index 508ed6bb787..00000000000
--- a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.releaseOrMint.t.sol
+++ /dev/null
@@ -1,35 +0,0 @@
-// SPDX-License-Identifier: BUSL-1.1
-pragma solidity ^0.8.24;
-
-import {Pool} from "../../../libraries/Pool.sol";
-import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol";
-
-import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol";
-
-contract BurnToAddressMintTokenPool_releaseOrMint is BurnToAddressMintTokenPoolSetup {
- function test_releaseOrMint() public {
- uint256 amount = 1e24;
- address receiver = makeAddr("RECEIVER_ADDRESS");
-
- vm.startPrank(s_burnMintOffRamp);
-
- vm.expectEmit();
- emit IERC20.Transfer(address(0), receiver, amount);
-
- s_pool.releaseOrMint(
- Pool.ReleaseOrMintInV1({
- originalSender: bytes(""),
- receiver: receiver,
- amount: amount,
- localToken: address(s_burnMintERC20),
- remoteChainSelector: DEST_CHAIN_SELECTOR,
- sourcePoolAddress: abi.encode(s_remoteBurnMintPool),
- sourcePoolData: "",
- offchainTokenData: ""
- })
- );
-
- assertEq(s_burnMintERC20.balanceOf(receiver), amount);
- assertEq(s_pool.getOutstandingTokens(), amount);
- }
-}
diff --git a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol
deleted file mode 100644
index 11c615d8b2b..00000000000
--- a/contracts/src/v0.8/ccip/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.setMintedTokens.t.sol
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: BUSL-1.1
-pragma solidity ^0.8.24;
-
-import {BurnToAddressMintTokenPool} from "../../../pools/BurnToAddressMintTokenPool.sol";
-import {BurnToAddressMintTokenPoolSetup} from "./BurnToAddressMintTokenPoolSetup.t.sol";
-
-contract BurnToAddressMintTokenPool_setOutstandingokens is BurnToAddressMintTokenPoolSetup {
- function test_setOutstandingTokens() public {
- uint256 amount = 1e18;
-
- assertEq(s_pool.getOutstandingTokens(), 0);
-
- vm.expectEmit();
- emit BurnToAddressMintTokenPool.OutstandingTokensSet(amount, 0);
-
- s_pool.setOutstandingTokens(amount);
-
- assertEq(s_pool.getOutstandingTokens(), amount);
- }
-}
diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol
index 6af10971018..d38f0d87b7c 100644
--- a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol
+++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideLiquidity.t.sol
@@ -5,48 +5,14 @@ import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenP
import {TokenPool} from "../../../pools/TokenPool.sol";
import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol";
-contract SiloedLockReleaseTokenPool_provideLiqudity is SiloedLockReleaseTokenPoolSetup {
+contract SiloedLockReleaseTokenPool_provideLiquidity is SiloedLockReleaseTokenPoolSetup {
address public UNAUTHORIZED_ADDRESS = address(0xdeadbeef);
function setUp() public override {
super.setUp();
-
- s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER);
- }
-
- function test_ProvideLiquidity_UnsiloedChain() public {
- uint256 amount = 1e24;
-
- vm.expectEmit();
- emit SiloedLockReleaseTokenPool.LiquidityAdded(DEST_CHAIN_SELECTOR, OWNER, amount);
-
- s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, amount);
-
- assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount);
-
- // Since the funds for the destination chain are not siloed,
- // the locked token amount should not be increased
- assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), amount);
- assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount);
- }
-
- function test_ProvideLiquidity_SiloedChain() public {
- uint256 amount = 1e24;
-
- vm.expectEmit();
- emit SiloedLockReleaseTokenPool.LiquidityAdded(SILOED_CHAIN_SELECTOR, OWNER, amount);
-
- s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount);
-
- assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount);
-
- assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount);
-
- // Since the funds for the destination chain are not siloed, the locked token amount should not be increased
- assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0);
}
- function test_ProvideLiquidity_LegacyProvideLiquiditySelector() public {
+ function test_provideLiquidity() public {
uint256 amount = 1e24;
vm.expectEmit();
@@ -65,23 +31,7 @@ contract SiloedLockReleaseTokenPool_provideLiqudity is SiloedLockReleaseTokenPoo
// Reverts
- function test_ProvideLiquidity_RevertWhen_UnauthorizedForSiloedChain() public {
- vm.startPrank(UNAUTHORIZED_ADDRESS);
-
- vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS));
-
- s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, 1);
- }
-
- function test_ProvideLiquidity_RevertWhen_UnauthorizedForUnsiloedChain() public {
- vm.startPrank(UNAUTHORIZED_ADDRESS);
-
- vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS));
-
- s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, 1);
- }
-
- function test_ProvideLiquidity_RevertWhen_LegacyFunctionSelector_Unauthorized() public {
+ function test_RevertWhen_Unauthorized() public {
vm.startPrank(UNAUTHORIZED_ADDRESS);
vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS));
diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideSiloedLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideSiloedLiquidity.t.sol
new file mode 100644
index 00000000000..167671dfad0
--- /dev/null
+++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.provideSiloedLiquidity.t.sol
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: BUSL-1.1
+pragma solidity ^0.8.24;
+
+import {SiloedLockReleaseTokenPool} from "../../../pools/SiloedLockReleaseTokenPool.sol";
+import {TokenPool} from "../../../pools/TokenPool.sol";
+import {SiloedLockReleaseTokenPoolSetup} from "./SiloedLockReleaseTokenPoolSetup.t.sol";
+
+contract SiloedLockReleaseTokenPool_provideSiloedLiquidity is SiloedLockReleaseTokenPoolSetup {
+ address public UNAUTHORIZED_ADDRESS = address(0xdeadbeef);
+
+ function setUp() public override {
+ super.setUp();
+
+ s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER);
+ }
+
+ function test_UnsiloedChain() public {
+ uint256 amount = 1e24;
+
+ vm.expectEmit();
+ emit SiloedLockReleaseTokenPool.LiquidityAdded(DEST_CHAIN_SELECTOR, OWNER, amount);
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, amount);
+
+ assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount);
+
+ // Since the funds for the destination chain are not siloed,
+ // the locked token amount should not be increased
+ assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(DEST_CHAIN_SELECTOR), amount);
+ assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount);
+ }
+
+ function test_SiloedChain() public {
+ uint256 amount = 1e24;
+
+ vm.expectEmit();
+ emit SiloedLockReleaseTokenPool.LiquidityAdded(SILOED_CHAIN_SELECTOR, OWNER, amount);
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount);
+
+ assertEq(s_token.balanceOf(address(s_siloedLockReleaseTokenPool)), amount);
+ assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount);
+
+ // Since the funds for the destination chain are not siloed, the locked token amount should not be increased
+ assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), 0);
+ }
+
+ // Reverts
+
+ function test_RevertWhen_UnauthorizedForSiloedChain() public {
+ vm.startPrank(UNAUTHORIZED_ADDRESS);
+
+ vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS));
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, 1);
+ }
+
+ function test_RevertWhen_UnauthorizedForUnsiloedChain() public {
+ vm.startPrank(UNAUTHORIZED_ADDRESS);
+
+ vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, UNAUTHORIZED_ADDRESS));
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(DEST_CHAIN_SELECTOR, 1);
+ }
+
+ function test_RevertWhen_LiquidityAmountCannotBeZero() public {
+ vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.LiquidityAmountCannotBeZero.selector));
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, 0);
+ }
+
+ function test_RevertWhen_InvalidChainSelector_Zero() public {
+ vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.InvalidChainSelector.selector, 0));
+
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(0, 1);
+ }
+}
diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol
index ea676d53015..661381038ae 100644
--- a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol
+++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.setRebalancer.t.sol
@@ -9,7 +9,7 @@ contract SiloedLockReleaseTokenPool_setRebalancer is SiloedLockReleaseTokenPoolS
function test_setSiloRebalancer() public {
vm.expectEmit();
- emit SiloedLockReleaseTokenPool.SiloRebalancerSet(SILOED_CHAIN_SELECTOR, REBALANCER_ADDRESS, OWNER);
+ emit SiloedLockReleaseTokenPool.SiloRebalancerSet(SILOED_CHAIN_SELECTOR, OWNER, REBALANCER_ADDRESS);
s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, REBALANCER_ADDRESS);
@@ -19,11 +19,12 @@ contract SiloedLockReleaseTokenPool_setRebalancer is SiloedLockReleaseTokenPoolS
function test_setRebalancer_UnsiloedChains() public {
vm.expectEmit();
- emit SiloedLockReleaseTokenPool.UnsiloedRebalancerSet(REBALANCER_ADDRESS, OWNER);
+ emit SiloedLockReleaseTokenPool.UnsiloedRebalancerSet(OWNER, REBALANCER_ADDRESS);
s_siloedLockReleaseTokenPool.setRebalancer(REBALANCER_ADDRESS);
assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(DEST_CHAIN_SELECTOR), REBALANCER_ADDRESS);
+ assertEq(s_siloedLockReleaseTokenPool.getRebalancer(), REBALANCER_ADDRESS);
}
// Reverts
diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol
index 506b1373ceb..38fdff34871 100644
--- a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol
+++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.updateSiloDesignations.t.sol
@@ -8,24 +8,7 @@ contract SiloedLockReleaseTokenPool_updateSiloDesignations is SiloedLockReleaseT
function test_updateSiloDesignations() public {
uint256 amount = 1e18;
- SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory chainSelectors =
- new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1);
-
- chainSelectors[0] =
- SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: SILOED_CHAIN_SELECTOR, rebalancer: OWNER});
-
- vm.expectEmit();
- emit SiloedLockReleaseTokenPool.ChainSiloed(SILOED_CHAIN_SELECTOR, OWNER);
-
- s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), chainSelectors);
-
- // Assert that the funds are siloed correctly
- assertTrue(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR));
- assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0);
- assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(SILOED_CHAIN_SELECTOR), OWNER);
-
// Provide some Liquidity so that we can then check that it gets removed.
- s_siloedLockReleaseTokenPool.setSiloRebalancer(SILOED_CHAIN_SELECTOR, OWNER);
s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount);
assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount);
@@ -47,6 +30,27 @@ contract SiloedLockReleaseTokenPool_updateSiloDesignations is SiloedLockReleaseT
// Assert that the available liquidity moved from being siloed to unsiloed.
assertEq(s_siloedLockReleaseTokenPool.getUnsiloedLiquidity(), amount);
+
+ // Now we re-silo the chain
+ SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory chainSelectors =
+ new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1);
+
+ chainSelectors[0] =
+ SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: SILOED_CHAIN_SELECTOR, rebalancer: OWNER});
+
+ vm.expectEmit();
+ emit SiloedLockReleaseTokenPool.ChainSiloed(SILOED_CHAIN_SELECTOR, OWNER);
+
+ s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), chainSelectors);
+
+ // Assert that the funds are siloed correctly
+ assertTrue(s_siloedLockReleaseTokenPool.isSiloed(SILOED_CHAIN_SELECTOR));
+ assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), 0);
+ assertEq(s_siloedLockReleaseTokenPool.getSiloRebalancer(SILOED_CHAIN_SELECTOR), OWNER);
+
+ // Provide some Liquidity so that we can then check that it gets removed.
+ s_siloedLockReleaseTokenPool.provideSiloedLiquidity(SILOED_CHAIN_SELECTOR, amount);
+ assertEq(s_siloedLockReleaseTokenPool.getAvailableTokens(SILOED_CHAIN_SELECTOR), amount);
}
// Reverts
@@ -62,12 +66,26 @@ contract SiloedLockReleaseTokenPool_updateSiloDesignations is SiloedLockReleaseT
);
}
- function test_updateSiloDesignations_RevertWhen_InvalidChainSelector() public {
+ function test_updateSiloDesignations_RevertWhen_InvalidChainSelector_ChainSelectorZero() public {
SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory adds = new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1);
adds[0] = SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: 0, rebalancer: OWNER});
+ // Chain selector cannot be zero
vm.expectRevert(abi.encodeWithSelector(SiloedLockReleaseTokenPool.InvalidChainSelector.selector, 0));
s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), adds);
}
+
+ function test_updateSiloDesignations_RevertWhen_InvalidChainSelector_ChainAlreadySiloed() public {
+ SiloedLockReleaseTokenPool.SiloConfigUpdate[] memory adds = new SiloedLockReleaseTokenPool.SiloConfigUpdate[](1);
+ adds[0] =
+ SiloedLockReleaseTokenPool.SiloConfigUpdate({remoteChainSelector: SILOED_CHAIN_SELECTOR, rebalancer: OWNER});
+
+ // Since the chain is already siloed you cannot re-silo it.
+ vm.expectRevert(
+ abi.encodeWithSelector(SiloedLockReleaseTokenPool.InvalidChainSelector.selector, SILOED_CHAIN_SELECTOR)
+ );
+
+ s_siloedLockReleaseTokenPool.updateSiloDesignations(new uint64[](0), adds);
+ }
}
diff --git a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol
index 7a82f0954a0..ab9c58b2a38 100644
--- a/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol
+++ b/contracts/src/v0.8/ccip/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.withdrawLiquidity.t.sol
@@ -123,4 +123,10 @@ contract SiloedLockReleaseTokenPool_withdrawLiqudity is SiloedLockReleaseTokenPo
s_siloedLockReleaseTokenPool.withdrawLiquidity(1);
}
+
+ function test_withdrawLiquidity_RevertWhen_LiquidityAmountCannotBeZero() public {
+ vm.expectRevert(SiloedLockReleaseTokenPool.LiquidityAmountCannotBeZero.selector);
+
+ s_siloedLockReleaseTokenPool.withdrawLiquidity(0);
+ }
}
diff --git a/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol b/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol
index 5a7dda0607f..08bc1fa1efc 100644
--- a/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol
+++ b/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol
@@ -3,10 +3,9 @@ pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
-import {WETH9} from "../../ccip/test/WETH9.sol";
-
import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol";
import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {WETH9} from "../../vendor/canonical-weth/WETH9.sol";
contract LiquidityManagerBaseTest is Test {
IERC20 internal s_l1Token;
diff --git a/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol b/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol
index cface1d5067..3a49dbd14c7 100644
--- a/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol
+++ b/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol
@@ -4,7 +4,6 @@ pragma solidity 0.8.24;
import "forge-std/Test.sol";
import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol";
-import {WETH9} from "../../../ccip/test/WETH9.sol";
import {OptimismL1BridgeAdapter} from "../../bridge-adapters/OptimismL1BridgeAdapter.sol";
import {Types} from "../../interfaces/optimism/Types.sol";
import {IOptimismPortal} from "../../interfaces/optimism/IOptimismPortal.sol";
@@ -12,6 +11,7 @@ import {IOptimismPortal} from "../../interfaces/optimism/IOptimismPortal.sol";
import {IL1StandardBridge} from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol";
import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
+import {WETH9} from "../../../vendor/canonical-weth/WETH9.sol";
contract OptimismL1BridgeAdapterSetup is Test {
// addresses below are fake
diff --git a/contracts/src/v0.8/ccip/test/WETH9.sol b/contracts/src/v0.8/vendor/canonical-weth/WETH9.sol
similarity index 99%
rename from contracts/src/v0.8/ccip/test/WETH9.sol
rename to contracts/src/v0.8/vendor/canonical-weth/WETH9.sol
index 0ac79d413dd..51aec423896 100644
--- a/contracts/src/v0.8/ccip/test/WETH9.sol
+++ b/contracts/src/v0.8/vendor/canonical-weth/WETH9.sol
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-pragma solidity ^0.8.24;
+pragma solidity ^0.8.0;
// solhint-disable
contract WETH9 {
diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol b/contracts/src/v0.8/workflow/WorkflowRegistry.sol
similarity index 98%
rename from contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol
rename to contracts/src/v0.8/workflow/WorkflowRegistry.sol
index 2a5f797d3c8..1ea64a0bf28 100644
--- a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol
+++ b/contracts/src/v0.8/workflow/WorkflowRegistry.sol
@@ -1,19 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";
+import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
-import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol";
+import {Ownable2StepMsgSender} from "../shared/access/Ownable2StepMsgSender.sol";
-import {Strings} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol";
-import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol";
+import {Strings} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol";
+import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol";
contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.UintSet;
- string public constant override typeAndVersion = "WorkflowRegistry 1.0.0-dev";
+ string public constant override typeAndVersion = "WorkflowRegistry 1.0.0";
uint8 private constant MAX_WORKFLOW_NAME_LENGTH = 64;
uint8 private constant MAX_URL_LENGTH = 200;
uint8 private constant MAX_PAGINATION_LIMIT = 100;
diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol b/contracts/src/v0.8/workflow/WorkflowRegistryManager.sol
similarity index 98%
rename from contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol
rename to contracts/src/v0.8/workflow/WorkflowRegistryManager.sol
index cf55aaeffb8..a5df400cf27 100644
--- a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol
+++ b/contracts/src/v0.8/workflow/WorkflowRegistryManager.sol
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";
+import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
-import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol";
+import {Ownable2StepMsgSender} from "../shared/access/Ownable2StepMsgSender.sol";
/// @title WorkflowRegistryManager
/// @notice This contract manages the versions of WorkflowRegistry contracts deployed over time.
@@ -11,7 +11,7 @@ import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.s
/// deployment information for each version, including deployment timestamp, chain ID, and active status. Only one
/// version can be active at any given time.
contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion {
- string public constant override typeAndVersion = "WorkflowRegistryManager 1.0.0-dev";
+ string public constant override typeAndVersion = "WorkflowRegistryManager 1.0.0";
uint8 private constant MAX_PAGINATION_LIMIT = 100;
struct Version {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol
index 3b2bc854325..4dbfcfee262 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_activateWorkflow is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol
index 974a3590f03..b13315dbaa5 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_deleteWorkflow is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol
index 5bc78feb0f2..5f914bc687d 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_getWorkflowMetadata is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol
index dbe0b23e5f0..e889b6c1b4f 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistryWithFixture} from "./WorkflowRegistryWithFixture.t.sol";
contract WorkflowRegistry_getWorkflowMetadataListByDON is WorkflowRegistryWithFixture {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol
index ceeddca969b..25ce036d89d 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistryWithFixture} from "./WorkflowRegistryWithFixture.t.sol";
contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWithFixture {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol
index 5c93c56acee..0dc82909365 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_lockRegistry is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol
index 1271808e85f..1e4be3dbce2 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_pauseWorkflow is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol
index c44c28520a4..ee00cca8a1f 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_registerWorkflow is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.requestForceUpdateSecrets.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.requestForceUpdateSecrets.t.sol
index d42368f22cc..b71035f106d 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.requestForceUpdateSecrets.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.requestForceUpdateSecrets.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
import {Vm} from "forge-std/Vm.sol";
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol
index 1cb2eb6429d..675d47832d1 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_unlockRegistry is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol
index bbf048909b5..7dd92970701 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_updateAllowedDONs is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol
index 01a3ded2c19..941e8dca590 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_updateAuthorizedAddresses is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol
index b60d44d8df6..0c2d896879e 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol
index b263b1cb79a..f504e729bcc 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {Test} from "forge-std/Test.sol";
contract WorkflowRegistrySetup is Test {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistryWithFixture.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistryWithFixture.t.sol
index 6c24a2d8f59..7d79900e951 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistryWithFixture.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistryWithFixture.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol";
+import {WorkflowRegistry} from "../../WorkflowRegistry.sol";
import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol";
contract WorkflowRegistryWithFixture is WorkflowRegistrySetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol
index a4c4975c3d4..d45a4a0b579 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
import {Vm} from "forge-std/Vm.sol";
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol
index 79eec6f71e5..f35d732a378 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol
@@ -2,7 +2,7 @@
pragma solidity 0.8.24;
import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol";
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {MockContract} from "../../mocks/MockContract.sol";
import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol
index 92d59346032..0fbc9deae9d 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
contract WorkflowRegistryManager_getActiveVersion is WorkflowRegistryManagerSetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol
index 4167dcc803a..8cfdf11fe3f 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
contract WorkflowRegistryManager_getActiveVersionNumber is WorkflowRegistryManagerSetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol
index ccdfacb474f..138998a82e5 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol
index 9ca2347d8a6..1b48330e1b0 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
contract WorkflowRegistryManager_getLatestVersion is WorkflowRegistryManagerSetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol
index 4ac9afc6ea6..f2d203aff05 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
contract WorkflowRegistryManager_getLatestVersionNumber is WorkflowRegistryManagerSetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol
index 1c8ea44408f..fc172f5bcab 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol
@@ -3,7 +3,7 @@ pragma solidity 0.8.24;
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
// import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol";
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
contract WorkflowRegistryManager_getVersion is WorkflowRegistryManagerSetup {
function test_WhenVersionNumberIsNotRegistered() external {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol
index a16ad878fc8..ba79246f3d9 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol";
contract WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID is WorkflowRegistryManagerSetup {
diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol
index 4e271aa5591..9308d077af3 100644
--- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol
+++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
-import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol";
+import {WorkflowRegistryManager} from "../../WorkflowRegistryManager.sol";
import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol";
import {Test} from "forge-std/Test.sol";
diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go
index 02c398db47a..6433f1667e3 100644
--- a/core/capabilities/ccip/delegate.go
+++ b/core/capabilities/ccip/delegate.go
@@ -39,6 +39,7 @@ import (
p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer"
+ "github.com/smartcontractkit/chainlink/v2/core/services/relay"
"github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/plugins"
@@ -265,22 +266,39 @@ func (d *Delegate) getOCRKeys(ocrKeyBundleIDs job.JSONConfig) (map[string]ocr2ke
func (d *Delegate) getTransmitterKeys(ctx context.Context, relayIDs []types.RelayID) (map[types.RelayID][]string, error) {
transmitterKeys := make(map[types.RelayID][]string)
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)
- }
+ switch relayID.Network {
+ case relay.NetworkSolana:
+ solKeys, err := d.keystore.Solana().GetAll()
+ if err != nil {
+ return nil, fmt.Errorf("error getting enabled addresses for chain: %s %w", relayID.ChainID, err)
+ }
- 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) {
+ for _, key := range solKeys {
+ r = append(r, key.PublicKey().String())
+ }
+ return
+ }()
+ case relay.NetworkEVM:
+ 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)
+ }
- transmitterKeys[relayID] = func() (r []string) {
- for _, key := range ethKeys {
- r = append(r, key.Hex())
+ 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)
}
- return
- }()
+
+ transmitterKeys[relayID] = func() (r []string) {
+ for _, key := range ethKeys {
+ r = append(r, key.Hex())
+ }
+ return
+ }()
+ default:
+ return nil, fmt.Errorf("unsupported network: %s", relayID.Network)
+ }
}
return transmitterKeys, nil
}
diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go
index 04d583460ff..62a864675f0 100644
--- a/core/capabilities/compute/compute.go
+++ b/core/capabilities/compute/compute.go
@@ -26,7 +26,6 @@ import (
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"
"github.com/smartcontractkit/chainlink/v2/core/platform"
@@ -76,10 +75,15 @@ var (
var _ capabilities.ActionCapability = (*Compute)(nil)
+type FetcherFn func(ctx context.Context, req *wasmpb.FetchRequest) (*wasmpb.FetchResponse, error)
+
+type FetcherFactory interface {
+ NewFetcher(log logger.Logger, emitter custmsg.MessageEmitter) FetcherFn
+}
+
type Compute struct {
- stopCh services.StopChan
- log logger.Logger
- metrics *computeMetricsLabeler
+ stopCh services.StopChan
+ log logger.Logger
// emitter is used to emit messages from the WASM module to a configured collector.
emitter custmsg.MessageEmitter
@@ -88,9 +92,9 @@ type Compute struct {
// transformer is used to transform a values.Map into a ParsedConfig struct on each execution
// of a request.
- transformer *transformer
- outgoingConnectorHandler *webapi.OutgoingConnectorHandler
- idGenerator func() string
+ transformer *transformer
+
+ fetcherFactory FetcherFactory
numWorkers int
queue chan request
@@ -185,7 +189,8 @@ func (c *Compute) execute(ctx context.Context, respCh chan response, req capabil
func (c *Compute) initModule(id string, cfg *host.ModuleConfig, binary []byte, requestMetadata capabilities.RequestMetadata) (*module, error) {
initStart := time.Now()
- cfg.Fetch = c.createFetcher()
+ cfg.Fetch = c.fetcherFactory.NewFetcher(c.log, c.emitter)
+
mod, err := host.NewModule(cfg, binary)
if err != nil {
return nil, fmt.Errorf("failed to instantiate WASM module: %w", err)
@@ -292,7 +297,31 @@ func (c *Compute) Close() error {
return nil
}
-func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchRequest) (*wasmpb.FetchResponse, error) {
+type outgoingConnectorFetcherFactory struct {
+ outgoingConnectorHandler *webapi.OutgoingConnectorHandler
+ idGenerator func() string
+ metrics *computeMetricsLabeler
+}
+
+func NewOutgoingConnectorFetcherFactory(
+ outgoingConnectorHandler *webapi.OutgoingConnectorHandler,
+ idGenerator func() string,
+) (FetcherFactory, error) {
+ metricsLabeler, err := newComputeMetricsLabeler(metrics.NewLabeler().With("capability", CapabilityIDCompute))
+ if err != nil {
+ return nil, fmt.Errorf("failed to create compute metrics labeler: %w", err)
+ }
+
+ factory := &outgoingConnectorFetcherFactory{
+ outgoingConnectorHandler: outgoingConnectorHandler,
+ idGenerator: idGenerator,
+ metrics: metricsLabeler,
+ }
+
+ return factory, nil
+}
+
+func (f *outgoingConnectorFetcherFactory) NewFetcher(log logger.Logger, emitter custmsg.MessageEmitter) FetcherFn {
return func(ctx context.Context, req *wasmpb.FetchRequest) (*wasmpb.FetchResponse, error) {
if err := validation.ValidateWorkflowOrExecutionID(req.Metadata.WorkflowId); err != nil {
return nil, fmt.Errorf("workflow ID %q is invalid: %w", req.Metadata.WorkflowId, err)
@@ -301,7 +330,7 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
return nil, fmt.Errorf("workflow execution ID %q is invalid: %w", req.Metadata.WorkflowExecutionId, err)
}
- cma := c.emitter.With(
+ cma := emitter.With(
platform.KeyWorkflowID, req.Metadata.WorkflowId,
platform.KeyWorkflowName, req.Metadata.DecodedWorkflowName,
platform.KeyWorkflowOwner, req.Metadata.WorkflowOwner,
@@ -312,7 +341,7 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
messageID := strings.Join([]string{
req.Metadata.WorkflowExecutionId,
ghcapabilities.MethodComputeAction,
- c.idGenerator(),
+ f.idGenerator(),
}, "/")
fields := req.Headers.GetFields()
@@ -321,7 +350,7 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
headersReq[k] = v.String()
}
- resp, err := c.outgoingConnectorHandler.HandleSingleNodeRequest(ctx, messageID, ghcapabilities.Request{
+ resp, err := f.outgoingConnectorHandler.HandleSingleNodeRequest(ctx, messageID, ghcapabilities.Request{
URL: req.Url,
Method: req.Method,
Headers: headersReq,
@@ -332,14 +361,14 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
return nil, err
}
- c.log.Debugw("received gateway response", "resp", resp)
+ 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)
}
- c.metrics.with(
+ f.metrics.with(
"status", strconv.FormatUint(uint64(response.StatusCode), 10),
platform.KeyWorkflowID, req.Metadata.WorkflowId,
platform.KeyWorkflowName, req.Metadata.WorkflowName,
@@ -351,7 +380,7 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
msg := fmt.Sprintf("compute fetch request failed with status code %d", response.StatusCode)
err = cma.Emit(ctx, msg)
if err != nil {
- c.log.Errorf("failed to send custom message with msg: %s, err: %v", msg, err)
+ log.Errorf("failed to send custom message with msg: %s, err: %v", msg, err)
}
}
@@ -360,18 +389,22 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq
}
const (
- defaultNumWorkers = 3
- defaultMaxMemoryMBs = 128
- defaultMaxTickInterval = 100 * time.Millisecond
- defaultMaxTimeout = 10 * time.Second
+ defaultNumWorkers = 3
+ defaultMaxMemoryMBs = 128
+ defaultMaxTickInterval = 100 * time.Millisecond
+ defaultMaxTimeout = 10 * time.Second
+ defaultMaxCompressedBinarySize = 20 * 1024 * 1024 // 20 MB
+ defaultMaxDecompressedBinarySize = 100 * 1024 * 1024 // 100 MB
)
type Config struct {
webapi.ServiceConfig
- NumWorkers int
- MaxMemoryMBs uint64
- MaxTimeout time.Duration
- MaxTickInterval time.Duration
+ NumWorkers int
+ MaxMemoryMBs uint64
+ MaxTimeout time.Duration
+ MaxTickInterval time.Duration
+ MaxCompressedBinarySize uint64
+ MaxDecompressedBinarySize uint64
}
func (c *Config) ApplyDefaults() {
@@ -387,36 +420,36 @@ func (c *Config) ApplyDefaults() {
if c.MaxTickInterval == 0 {
c.MaxTickInterval = defaultMaxTickInterval
}
+ if c.MaxCompressedBinarySize == 0 {
+ c.MaxCompressedBinarySize = uint64(defaultMaxCompressedBinarySize)
+ }
+ if c.MaxDecompressedBinarySize == 0 {
+ c.MaxDecompressedBinarySize = uint64(defaultMaxDecompressedBinarySize)
+ }
}
func NewAction(
config Config,
log logger.Logger,
registry coretypes.CapabilitiesRegistry,
- handler *webapi.OutgoingConnectorHandler,
- idGenerator func() string,
+ fetcherFactory FetcherFactory,
opts ...func(*Compute),
) (*Compute, error) {
config.ApplyDefaults()
- metricsLabeler, err := newComputeMetricsLabeler(metrics.NewLabeler().With("capability", CapabilityIDCompute))
- if err != nil {
- return nil, fmt.Errorf("failed to create compute metrics labeler: %w", err)
- }
+
var (
lggr = logger.Named(log, "CustomCompute")
labeler = custmsg.NewLabeler()
compute = &Compute{
- stopCh: make(services.StopChan),
- log: lggr,
- emitter: labeler,
- metrics: metricsLabeler,
- registry: registry,
- modules: newModuleCache(clockwork.NewRealClock(), 1*time.Minute, 10*time.Minute, 3),
- transformer: NewTransformer(lggr, labeler, config),
- outgoingConnectorHandler: handler,
- idGenerator: idGenerator,
- queue: make(chan request),
- numWorkers: config.NumWorkers,
+ stopCh: make(services.StopChan),
+ log: lggr,
+ emitter: labeler,
+ registry: registry,
+ modules: newModuleCache(clockwork.NewRealClock(), 1*time.Minute, 10*time.Minute, 3),
+ transformer: NewTransformer(lggr, labeler, config),
+ fetcherFactory: fetcherFactory,
+ queue: make(chan request),
+ numWorkers: config.NumWorkers,
}
)
diff --git a/core/capabilities/compute/compute_test.go b/core/capabilities/compute/compute_test.go
index 98c8223409d..d5411d8ced2 100644
--- a/core/capabilities/compute/compute_test.go
+++ b/core/capabilities/compute/compute_test.go
@@ -62,7 +62,9 @@ func setup(t *testing.T, config Config) testHarness {
connectorHandler, err := webapi.NewOutgoingConnectorHandler(connector, config.ServiceConfig, ghcapabilities.MethodComputeAction, log)
require.NoError(t, err)
- compute, err := NewAction(config, log, registry, connectorHandler, idGeneratorFn)
+ fetchFactory, err := NewOutgoingConnectorFetcherFactory(connectorHandler, idGeneratorFn)
+ require.NoError(t, err)
+ compute, err := NewAction(config, log, registry, fetchFactory)
require.NoError(t, err)
compute.modules.clock = clockwork.NewFakeClock()
diff --git a/core/capabilities/integration_tests/framework/don.go b/core/capabilities/integration_tests/framework/don.go
index c1a3cada4bc..c2a808ee019 100644
--- a/core/capabilities/integration_tests/framework/don.go
+++ b/core/capabilities/integration_tests/framework/don.go
@@ -3,6 +3,7 @@ package framework
import (
"context"
"encoding/hex"
+ "errors"
"fmt"
"strconv"
"testing"
@@ -14,6 +15,9 @@ import (
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
+ "github.com/smartcontractkit/chainlink/v2/core/capabilities/compute"
+ "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer"
+
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"
@@ -41,9 +45,12 @@ import (
)
type DonContext struct {
- EthBlockchain *EthBlockchain
- p2pNetwork *FakeRageP2PNetwork
- capabilityRegistry *CapabilitiesRegistry
+ EthBlockchain *EthBlockchain
+ p2pNetwork *FakeRageP2PNetwork
+ capabilityRegistry *CapabilitiesRegistry
+ workflowRegistry *WorkflowRegistry
+ syncerFetcherFunc syncer.FetcherFunc
+ computeFetcherFactory compute.FetcherFactory
}
func CreateDonContext(ctx context.Context, t *testing.T) DonContext {
@@ -56,6 +63,16 @@ func CreateDonContext(ctx context.Context, t *testing.T) DonContext {
return DonContext{EthBlockchain: ethBlockchain, p2pNetwork: rageP2PNetwork, capabilityRegistry: capabilitiesRegistry}
}
+func CreateDonContextWithWorkflowRegistry(ctx context.Context, t *testing.T, syncerFetcherFunc syncer.FetcherFunc,
+ computeFetcherFactory compute.FetcherFactory) DonContext {
+ donContext := CreateDonContext(ctx, t)
+ workflowRegistry := NewWorkflowRegistry(ctx, t, donContext.EthBlockchain)
+ donContext.workflowRegistry = workflowRegistry
+ donContext.syncerFetcherFunc = syncerFetcherFunc
+ donContext.computeFetcherFactory = computeFetcherFactory
+ return donContext
+}
+
func (c DonContext) WaitForCapabilitiesToBeExposed(t *testing.T, dons ...*DON) {
allExpectedCapabilities := make(map[CapabilityRegistration]bool)
for _, don := range dons {
@@ -91,15 +108,21 @@ type capabilityNode struct {
type DON struct {
services.StateMachine
t *testing.T
+ id *uint32
config DonConfiguration
lggr logger.Logger
nodes []*capabilityNode
standardCapabilityJobs []*job.Job
publishedCapabilities []capability
- capabilitiesRegistry *CapabilitiesRegistry
+
+ initialised bool
+
+ capabilitiesRegistry *CapabilitiesRegistry
+ workflowRegistry *WorkflowRegistry
nodeConfigModifiers []func(c *chainlink.Config, node *capabilityNode)
+ fakeLibOcr *FakeLibOCR
addOCR3NonStandardCapability bool
triggerFactories []TriggerFactory
@@ -107,17 +130,15 @@ type DON struct {
}
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}
-
- protocolRoundInterval := 1 * time.Second
+ dependentDONs []commoncap.DON, donContext DonContext, supportsOCR bool, protocolRoundInterval time.Duration) *DON {
+ don := &DON{t: t, lggr: lggr.Named(donConfig.name), config: donConfig, capabilitiesRegistry: donContext.capabilityRegistry,
+ workflowRegistry: donContext.workflowRegistry}
var newOracleFactoryFn standardcapabilities.NewOracleFactoryFn
- var libOcr *FakeLibOCR
if supportsOCR {
// This is required to support the non standard OCR3 capability - will be removed when required OCR3 behaviour is implemented as standard capabilities
- libOcr = NewFakeLibOCR(t, lggr, donConfig.F, protocolRoundInterval)
- servicetest.Run(t, libOcr)
+ don.fakeLibOcr = NewFakeLibOCR(t, lggr, donConfig.F, protocolRoundInterval)
+ servicetest.Run(t, don.fakeLibOcr)
}
for i, member := range donConfig.Members {
@@ -152,7 +173,7 @@ func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig Don
for _, modifier := range don.nodeConfigModifiers {
modifier(c, cn)
}
- })
+ }, donContext.syncerFetcherFunc, donContext.computeFetcherFactory)
require.NoError(t, node.Start(testutils.Context(t)))
cn.TestApplication = node
@@ -168,6 +189,16 @@ func (d *DON) Initialise() {
//nolint:gosec // disable G115
d.config.DON.ID = uint32(id)
+ d.id = &d.config.DON.ID
+
+ if d.config.AcceptsWorkflows && d.workflowRegistry != nil {
+ d.workflowRegistry.UpdateAllowedDons([]uint32{d.config.DON.ID})
+ d.nodeConfigModifiers = append(d.nodeConfigModifiers, func(c *chainlink.Config, node *capabilityNode) {
+ workflowRegistryAddressStr := d.workflowRegistry.addr.String()
+ c.Capabilities.WorkflowRegistry.Address = &workflowRegistryAddressStr
+ })
+ }
+ d.initialised = true
}
func (d *DON) GetID() uint32 {
@@ -237,11 +268,12 @@ func (d *DON) Start(ctx context.Context) error {
}
if d.addOCR3NonStandardCapability {
- libocr := NewFakeLibOCR(d.t, d.lggr, d.config.F, 1*time.Second)
- servicetest.Run(d.t, libocr)
+ if d.fakeLibOcr == nil {
+ return errors.New("don does not support OCR")
+ }
for _, node := range d.nodes {
- addOCR3Capability(ctx, d.t, d.lggr, node.registry, libocr, d.config.F, node.KeyBundle)
+ addOCR3Capability(ctx, d.t, d.lggr, node.registry, d.fakeLibOcr, d.config.F, node.KeyBundle)
}
}
@@ -342,6 +374,20 @@ func (d *DON) AddJob(ctx context.Context, j *job.Job) error {
return nil
}
+func (d *DON) AddWorkflow(workflow Workflow) error {
+ if !d.config.AcceptsWorkflows {
+ return errors.New("cannot add workflow to non-workflow DON")
+ }
+
+ if !d.initialised {
+ return errors.New("cannot add workflow to non-initialised DON")
+ }
+
+ d.workflowRegistry.RegisterWorkflow(workflow, *d.id)
+
+ return nil
+}
+
type TriggerFactory interface {
CreateNewTrigger(t *testing.T) commoncap.TriggerCapability
GetTriggerID() string
@@ -365,12 +411,15 @@ func startNewNode(ctx context.Context,
newOracleFactoryFn standardcapabilities.NewOracleFactoryFn,
keyV2 ethkey.KeyV2,
setupCfg func(c *chainlink.Config),
+ fetcherFunc syncer.FetcherFunc,
+ fetcherFactoryFunc compute.FetcherFactory,
) *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)
+ c.Feature.LogPoller = ptr(true)
if setupCfg != nil {
setupCfg(c)
@@ -393,7 +442,7 @@ func startNewNode(ctx context.Context,
ethBlockchain.Commit()
return cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, ethBlockchain.Backend, nodeInfo,
- dispatcher, peerWrapper, newOracleFactoryFn, localCapabilities, keyV2, lggr)
+ dispatcher, peerWrapper, newOracleFactoryFn, localCapabilities, keyV2, lggr, fetcherFunc, fetcherFactoryFunc)
}
// Functions below this point are for adding non-standard capabilities to a DON, deliberately verbose. Eventually these
@@ -415,24 +464,51 @@ func (d *DON) AddOCR3NonStandardCapability() {
})
}
-func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.Address) error {
+func (d *DON) AddPublishedEthereumWriteTargetNonStandardCapability(forwarderAddr common.Address) (string, error) {
+ published := true
+
+ capabilityID, s, err := d.addEthereumWriteTarget(forwarderAddr, published)
+ if err != nil {
+ return s, err
+ }
+
+ return capabilityID, nil
+}
+
+func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.Address) (string, error) {
+ published := false
+
+ capabilityID, s, err := d.addEthereumWriteTarget(forwarderAddr, published)
+ if err != nil {
+ return s, err
+ }
+
+ return capabilityID, nil
+}
+
+func (d *DON) addEthereumWriteTarget(forwarderAddr common.Address, published bool) (string, string, 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
})
+ labelledName := "write_geth-testnet"
+ version := "1.0.0"
+
writeChain := kcr.CapabilitiesRegistryCapability{
- LabelledName: "write_geth-testnet",
- Version: "1.0.0",
+ LabelledName: labelledName,
+ Version: version,
CapabilityType: uint8(registrysyncer.ContractCapabilityTypeTarget),
}
+ capabilityID := fmt.Sprintf("%s@%s", labelledName, version)
+
targetCapabilityConfig := newCapabilityConfig()
configWithLimit, err := values.WrapMap(map[string]any{"gasLimit": 500000})
if err != nil {
- return fmt.Errorf("failed to wrap map: %w", err)
+ return "", "", fmt.Errorf("failed to wrap map: %w", err)
}
targetCapabilityConfig.DefaultConfig = values.Proto(configWithLimit).GetMapValue()
@@ -443,12 +519,13 @@ func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.A
},
}
- d.publishedCapabilities = append(d.publishedCapabilities, capability{
- donCapabilityConfig: targetCapabilityConfig,
- registryConfig: writeChain,
- })
-
- return nil
+ if published {
+ d.publishedCapabilities = append(d.publishedCapabilities, capability{
+ donCapabilityConfig: targetCapabilityConfig,
+ registryConfig: writeChain,
+ })
+ }
+ return capabilityID, "", nil
}
func addOCR3Capability(ctx context.Context, t *testing.T, lggr logger.Logger, capabilityRegistry *capabilities.Registry,
diff --git a/core/capabilities/integration_tests/framework/don_configuration.go b/core/capabilities/integration_tests/framework/don_configuration.go
index 2fd1afd6554..f6ed34d65d8 100644
--- a/core/capabilities/integration_tests/framework/don_configuration.go
+++ b/core/capabilities/integration_tests/framework/don_configuration.go
@@ -30,7 +30,7 @@ func NewDonConfiguration(don NewDonConfigurationParams) (DonConfiguration, error
return DonConfiguration{}, fmt.Errorf("invalid configuration, number of nodes must be at least 3*F+1")
}
- keyBundles, peerIDs, err := getKeyBundlesAndPeerIDs(don.NumNodes)
+ keyBundles, peerIDs, err := getKeyBundlesAndPeerIDs(don.Name, don.NumNodes)
if err != nil {
return DonConfiguration{}, fmt.Errorf("failed to get key bundles and peer IDs: %w", err)
}
diff --git a/core/capabilities/integration_tests/framework/fake_libocr.go b/core/capabilities/integration_tests/framework/fake_libocr.go
index 0f378a39129..12ba070bc48 100644
--- a/core/capabilities/integration_tests/framework/fake_libocr.go
+++ b/core/capabilities/integration_tests/framework/fake_libocr.go
@@ -182,7 +182,9 @@ func (m *FakeLibOCR) Start(ctx context.Context) error {
case <-ctx.Done():
return
case <-ticker.C:
- err := m.simulateProtocolRound(ctx)
+ serviceCtx, cancel := m.stopCh.NewCtx()
+ err := m.simulateProtocolRound(serviceCtx)
+ cancel()
if err != nil {
m.lggr.Errorf("simulating protocol round: %v", err)
}
diff --git a/core/capabilities/integration_tests/framework/peer.go b/core/capabilities/integration_tests/framework/peer.go
index c4f73629450..c8fd7952483 100644
--- a/core/capabilities/integration_tests/framework/peer.go
+++ b/core/capabilities/integration_tests/framework/peer.go
@@ -2,7 +2,7 @@ package framework
import (
"context"
- "crypto/rand"
+ "crypto/sha256"
"encoding/hex"
"fmt"
"strings"
@@ -70,11 +70,11 @@ func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error
}, nil
}
-func getKeyBundlesAndPeerIDs(numNodes int) ([]ocr2key.KeyBundle, []peer, error) {
+func getKeyBundlesAndPeerIDs(donName string, numNodes int) ([]ocr2key.KeyBundle, []peer, error) {
var keyBundles []ocr2key.KeyBundle
var donPeerIDs []peer
for i := 0; i < numNodes; i++ {
- peerID := NewPeerID()
+ peerID := NewPeerID(donName, i)
keyBundle, err := ocr2key.New(chaintype.EVM)
if err != nil {
@@ -163,13 +163,9 @@ 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)
- }
-
+func NewPeerID(donName string, nodeOrdinal int) string {
+ privKeyString := fmt.Sprintf("privatekey:%s:%d", donName, nodeOrdinal)
+ privKey := sha256.Sum256([]byte(privKeyString))
peerID := append(libp2pMagic(), privKey[:]...)
return base58.Encode(peerID)
diff --git a/core/capabilities/integration_tests/framework/workflow_registry.go b/core/capabilities/integration_tests/framework/workflow_registry.go
new file mode 100644
index 00000000000..093c2757c2e
--- /dev/null
+++ b/core/capabilities/integration_tests/framework/workflow_registry.go
@@ -0,0 +1,105 @@
+package framework
+
+import (
+ "context"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper"
+)
+
+type WorkflowRegistry struct {
+ t *testing.T
+ backend *EthBlockchain
+ contract *workflow_registry_wrapper.WorkflowRegistry
+ addr common.Address
+}
+
+func NewWorkflowRegistry(ctx context.Context, t *testing.T, backend *EthBlockchain) *WorkflowRegistry {
+ // Deploy a test workflow_registry
+ wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backend.transactionOpts, backend.Backend.Client())
+ backend.Backend.Commit()
+ require.NoError(t, err)
+
+ // setup contract state to allow the secrets to be updated
+ updateAuthorizedAddress(t, backend, wfRegistryC, []common.Address{backend.transactionOpts.From}, true)
+
+ return &WorkflowRegistry{t: t, addr: wfRegistryAddr, contract: wfRegistryC, backend: backend}
+}
+
+func (r *WorkflowRegistry) UpdateAllowedDons(donIDs []uint32) {
+ updateAllowedDONs(r.t, r.backend, r.contract, donIDs, true)
+}
+
+func (r *WorkflowRegistry) RegisterWorkflow(input Workflow, donID uint32) {
+ registerWorkflow(r.t, r.backend, r.contract, input, donID)
+}
+
+func updateAuthorizedAddress(
+ t *testing.T,
+ th *EthBlockchain,
+ wfRegC *workflow_registry_wrapper.WorkflowRegistry,
+ addresses []common.Address,
+ _ bool,
+) {
+ t.Helper()
+ _, err := wfRegC.UpdateAuthorizedAddresses(th.transactionOpts, addresses, true)
+ require.NoError(t, err, "failed to update authorised addresses")
+ th.Backend.Commit()
+ th.Backend.Commit()
+ th.Backend.Commit()
+ gotAddresses, err := wfRegC.GetAllAuthorizedAddresses(&bind.CallOpts{
+ From: th.transactionOpts.From,
+ })
+ require.NoError(t, err)
+ require.ElementsMatch(t, addresses, gotAddresses)
+}
+
+func updateAllowedDONs(
+ t *testing.T,
+ th *EthBlockchain,
+ wfRegC *workflow_registry_wrapper.WorkflowRegistry,
+ donIDs []uint32,
+ allowed bool,
+) {
+ t.Helper()
+ _, err := wfRegC.UpdateAllowedDONs(th.transactionOpts, donIDs, allowed)
+ require.NoError(t, err, "failed to update DONs")
+ th.Backend.Commit()
+ th.Backend.Commit()
+ th.Backend.Commit()
+ gotDons, err := wfRegC.GetAllAllowedDONs(&bind.CallOpts{
+ From: th.transactionOpts.From,
+ })
+ require.NoError(t, err)
+ require.ElementsMatch(t, donIDs, gotDons)
+}
+
+type Workflow struct {
+ Name string
+ ID [32]byte
+ Status uint8
+ BinaryURL string
+ ConfigURL string
+ SecretsURL string
+}
+
+func registerWorkflow(
+ t *testing.T,
+ th *EthBlockchain,
+ wfRegC *workflow_registry_wrapper.WorkflowRegistry,
+ input Workflow,
+ donID uint32,
+) {
+ t.Helper()
+ _, err := wfRegC.RegisterWorkflow(th.transactionOpts, input.Name, input.ID, donID,
+ input.Status, input.BinaryURL, input.ConfigURL, input.SecretsURL)
+ require.NoError(t, err, "failed to register workflow")
+ th.Backend.Commit()
+ th.Backend.Commit()
+ th.Backend.Commit()
+}
diff --git a/core/capabilities/integration_tests/keystone/setup.go b/core/capabilities/integration_tests/keystone/setup.go
index 690e176e491..e36365fca12 100644
--- a/core/capabilities/integration_tests/keystone/setup.go
+++ b/core/capabilities/integration_tests/keystone/setup.go
@@ -5,6 +5,7 @@ import (
"encoding/hex"
"math/big"
"testing"
+ "time"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
@@ -60,7 +61,7 @@ func setupKeystoneDons(ctx context.Context, t *testing.T, lggr logger.SugaredLog
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)
+ []commoncap.DON{}, donContext, false, 1*time.Second)
triggerDon.AddExternalTriggerCapability(trigger)
triggerDon.Initialise()
@@ -69,8 +70,8 @@ func createKeystoneTriggerDon(ctx context.Context, t *testing.T, lggr logger.Sug
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)
+ []commoncap.DON{}, donContext, false, 1*time.Second)
+ _, err := writeTargetDon.AddPublishedEthereumWriteTargetNonStandardCapability(forwarderAddr)
require.NoError(t, err)
writeTargetDon.Initialise()
return writeTargetDon
@@ -80,7 +81,7 @@ func createKeystoneWorkflowDon(ctx context.Context, t *testing.T, lggr logger.Su
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)
+ donContext, true, 1*time.Second)
workflowDon.AddOCR3NonStandardCapability()
workflowDon.Initialise()
diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go
index 719b3e872cc..d788b688bc0 100644
--- a/core/capabilities/launcher.go
+++ b/core/capabilities/launcher.go
@@ -329,7 +329,7 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON registrysync
return fmt.Errorf("failed to add action shim: %w", err)
}
case capabilities.CapabilityTypeConsensus:
- w.lggr.Warn("no remote client configured for capability type consensus, skipping configuration")
+ // nothing to do; we don't support remote consensus capabilities for now
case capabilities.CapabilityTypeTarget:
newTargetFn := func(info capabilities.CapabilityInfo) (capabilityService, error) {
client := executable.NewClient(
diff --git a/core/capabilities/remote/executable/client_test.go b/core/capabilities/remote/executable/client_test.go
index 27e9974ce0e..20458eb3531 100644
--- a/core/capabilities/remote/executable/client_test.go
+++ b/core/capabilities/remote/executable/client_test.go
@@ -30,6 +30,8 @@ const (
)
func Test_Client_DonTopologies(t *testing.T) {
+ t.Skip("Flaking again: https://smartcontract-it.atlassian.net/browse/CAPPL-322")
+
ctx := testutils.Context(t)
transmissionSchedule, err := values.NewMap(map[string]any{
diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go
index 0675bcc0f2a..dcbca5d6398 100644
--- a/core/capabilities/remote/types/messages.pb.go
+++ b/core/capabilities/remote/types/messages.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.35.1
-// protoc v4.25.1
+// protoc-gen-go v1.36.4
+// protoc v5.29.3
// source: core/capabilities/remote/types/messages.proto
package types
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -79,12 +80,11 @@ func (Error) EnumDescriptor() ([]byte, []int) {
}
type Message struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
+ Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` // proto-encoded MessageBody to sign
unknownFields protoimpl.UnknownFields
-
- Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
- Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` // proto-encoded MessageBody to sign
+ sizeCache protoimpl.SizeCache
}
func (x *Message) Reset() {
@@ -132,28 +132,27 @@ func (x *Message) GetBody() []byte {
}
type MessageBody struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
- Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"`
- Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"`
- Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
- MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender
- CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"`
- Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"`
- Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"`
- ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"`
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
+ Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"`
+ Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"`
+ Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender
+ CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"`
+ Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"`
+ Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"`
+ ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"`
// payload contains a CapabilityRequest or CapabilityResponse
Payload []byte `protobuf:"bytes,12,opt,name=payload,proto3" json:"payload,omitempty"`
- // Types that are assignable to Metadata:
+ // Types that are valid to be assigned to Metadata:
//
// *MessageBody_TriggerRegistrationMetadata
// *MessageBody_TriggerEventMetadata
Metadata isMessageBody_Metadata `protobuf_oneof:"metadata"`
CapabilityDonId uint32 `protobuf:"varint,15,opt,name=capability_don_id,json=capabilityDonId,proto3" json:"capability_don_id,omitempty"`
CallerDonId uint32 `protobuf:"varint,16,opt,name=caller_don_id,json=callerDonId,proto3" json:"caller_don_id,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *MessageBody) Reset() {
@@ -256,23 +255,27 @@ func (x *MessageBody) GetPayload() []byte {
return nil
}
-func (m *MessageBody) GetMetadata() isMessageBody_Metadata {
- if m != nil {
- return m.Metadata
+func (x *MessageBody) GetMetadata() isMessageBody_Metadata {
+ if x != nil {
+ return x.Metadata
}
return nil
}
func (x *MessageBody) GetTriggerRegistrationMetadata() *TriggerRegistrationMetadata {
- if x, ok := x.GetMetadata().(*MessageBody_TriggerRegistrationMetadata); ok {
- return x.TriggerRegistrationMetadata
+ if x != nil {
+ if x, ok := x.Metadata.(*MessageBody_TriggerRegistrationMetadata); ok {
+ return x.TriggerRegistrationMetadata
+ }
}
return nil
}
func (x *MessageBody) GetTriggerEventMetadata() *TriggerEventMetadata {
- if x, ok := x.GetMetadata().(*MessageBody_TriggerEventMetadata); ok {
- return x.TriggerEventMetadata
+ if x != nil {
+ if x, ok := x.Metadata.(*MessageBody_TriggerEventMetadata); ok {
+ return x.TriggerEventMetadata
+ }
}
return nil
}
@@ -308,11 +311,10 @@ func (*MessageBody_TriggerRegistrationMetadata) isMessageBody_Metadata() {}
func (*MessageBody_TriggerEventMetadata) isMessageBody_Metadata() {}
type TriggerRegistrationMetadata struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- LastReceivedEventId string `protobuf:"bytes,1,opt,name=last_received_event_id,json=lastReceivedEventId,proto3" json:"last_received_event_id,omitempty"`
+ state protoimpl.MessageState `protogen:"open.v1"`
+ LastReceivedEventId string `protobuf:"bytes,1,opt,name=last_received_event_id,json=lastReceivedEventId,proto3" json:"last_received_event_id,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *TriggerRegistrationMetadata) Reset() {
@@ -353,12 +355,11 @@ func (x *TriggerRegistrationMetadata) GetLastReceivedEventId() string {
}
type TriggerEventMetadata struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- TriggerEventId string `protobuf:"bytes,1,opt,name=trigger_event_id,json=triggerEventId,proto3" json:"trigger_event_id,omitempty"`
- WorkflowIds []string `protobuf:"bytes,2,rep,name=workflow_ids,json=workflowIds,proto3" json:"workflow_ids,omitempty"`
+ state protoimpl.MessageState `protogen:"open.v1"`
+ TriggerEventId string `protobuf:"bytes,1,opt,name=trigger_event_id,json=triggerEventId,proto3" json:"trigger_event_id,omitempty"`
+ WorkflowIds []string `protobuf:"bytes,2,rep,name=workflow_ids,json=workflowIds,proto3" json:"workflow_ids,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *TriggerEventMetadata) Reset() {
@@ -407,7 +408,7 @@ func (x *TriggerEventMetadata) GetWorkflowIds() []string {
var File_core_capabilities_remote_types_messages_proto protoreflect.FileDescriptor
-var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{
+var file_core_capabilities_remote_types_messages_proto_rawDesc = string([]byte{
0x0a, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74,
0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73,
0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
@@ -475,16 +476,16 @@ var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{
0x05, 0x42, 0x20, 0x5a, 0x1e, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69,
0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79,
0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
var (
file_core_capabilities_remote_types_messages_proto_rawDescOnce sync.Once
- file_core_capabilities_remote_types_messages_proto_rawDescData = file_core_capabilities_remote_types_messages_proto_rawDesc
+ file_core_capabilities_remote_types_messages_proto_rawDescData []byte
)
func file_core_capabilities_remote_types_messages_proto_rawDescGZIP() []byte {
file_core_capabilities_remote_types_messages_proto_rawDescOnce.Do(func() {
- file_core_capabilities_remote_types_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_capabilities_remote_types_messages_proto_rawDescData)
+ file_core_capabilities_remote_types_messages_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_core_capabilities_remote_types_messages_proto_rawDesc), len(file_core_capabilities_remote_types_messages_proto_rawDesc)))
})
return file_core_capabilities_remote_types_messages_proto_rawDescData
}
@@ -522,7 +523,7 @@ func file_core_capabilities_remote_types_messages_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_core_capabilities_remote_types_messages_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_core_capabilities_remote_types_messages_proto_rawDesc), len(file_core_capabilities_remote_types_messages_proto_rawDesc)),
NumEnums: 1,
NumMessages: 4,
NumExtensions: 0,
@@ -534,7 +535,6 @@ func file_core_capabilities_remote_types_messages_proto_init() {
MessageInfos: file_core_capabilities_remote_types_messages_proto_msgTypes,
}.Build()
File_core_capabilities_remote_types_messages_proto = out.File
- file_core_capabilities_remote_types_messages_proto_rawDesc = nil
file_core_capabilities_remote_types_messages_proto_goTypes = nil
file_core_capabilities_remote_types_messages_proto_depIdxs = nil
}
diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go
index 3fc51270c86..a312518910b 100644
--- a/core/capabilities/targets/write_target.go
+++ b/core/capabilities/targets/write_target.go
@@ -5,6 +5,7 @@ import (
"context"
"encoding/binary"
"encoding/hex"
+ "errors"
"fmt"
"math/big"
"strings"
@@ -44,6 +45,13 @@ type WriteTarget struct {
bound bool
}
+const (
+ TransmissionStateNotAttempted uint8 = iota
+ TransmissionStateSucceeded
+ TransmissionStateInvalidReceiver
+ TransmissionStateFailed
+)
+
type TransmissionInfo struct {
GasLimit *big.Int
InvalidReceiver bool
@@ -243,30 +251,21 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap
}
// Check whether value was already transmitted on chain
- queryInputs := struct {
- Receiver string
- WorkflowExecutionID []byte
- ReportId []byte
- }{
- Receiver: request.Config.Address,
- WorkflowExecutionID: rawExecutionID,
- ReportId: request.Inputs.SignedReport.ID,
- }
- var transmissionInfo TransmissionInfo
- 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)
+ transmissionInfo, err := cap.getTransmissionInfo(ctx, request, rawExecutionID)
+ if err != nil {
+ return capabilities.CapabilityResponse{}, err
}
switch {
- case transmissionInfo.State == 0: // NOT_ATTEMPTED
+ case transmissionInfo.State == TransmissionStateNotAttempted:
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
+ case transmissionInfo.State == TransmissionStateSucceeded:
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
+ case transmissionInfo.State == TransmissionStateInvalidReceiver:
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
+ case transmissionInfo.State == TransmissionStateFailed:
receiverGasMinimum := cap.receiverGasMinimum
if request.Config.GasLimit != nil {
receiverGasMinimum = *request.Config.GasLimit - ForwarderContractLogicGasCost
@@ -340,6 +339,35 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap
continue
}
switch txStatus {
+ case commontypes.Pending:
+ cap.lggr.Debugw("Transaction pending, retrying...", "request", request, "transaction", txID)
+ // TxStatus Unconfirmed actually means "Confirmed" for the transaction manager, i.e. the transaction has landed on chain but isn't finalized.
+ case commontypes.Unconfirmed:
+ transmissionInfo, err = cap.getTransmissionInfo(ctx, request, rawExecutionID)
+ if err != nil {
+ return capabilities.CapabilityResponse{}, err
+ }
+
+ // This is counterintuitive, but the tx manager is currently returning unconfirmed whenever the tx is confirmed
+ // current implementation here: https://github.com/smartcontractkit/chainlink-framework/blob/main/chains/txmgr/txmgr.go#L697
+ // so we need to check if we where able to write to the consumer contract to determine if the transaction was successful
+ if transmissionInfo.State == TransmissionStateSucceeded {
+ cap.lggr.Debugw("Transaction confirmed", "request", request, "transaction", txID)
+ return capabilities.CapabilityResponse{}, nil
+ } else {
+ cap.lggr.Errorw("Transaction written to the forwarder, but failed to be written to the consumer contract", "request", request, "transaction", txID, "transmissionState", transmissionInfo.State)
+ msg := "failed to submit transaction with ID: " + txID.String()
+ err = cap.emitter.With(
+ platform.KeyWorkflowID, request.Metadata.WorkflowID,
+ platform.KeyWorkflowName, request.Metadata.DecodedWorkflowName,
+ platform.KeyWorkflowOwner, request.Metadata.WorkflowOwner,
+ platform.KeyWorkflowExecutionID, request.Metadata.WorkflowExecutionID,
+ ).Emit(ctx, msg)
+ if err != nil {
+ cap.lggr.Errorf("failed to send custom message with msg: %s, err: %v", msg, err)
+ }
+ return capabilities.CapabilityResponse{}, errors.New("submitted transaction failed")
+ }
case commontypes.Finalized:
cap.lggr.Debugw("Transaction finalized", "request", request, "transaction", txID)
return capabilities.CapabilityResponse{}, nil
@@ -356,7 +384,7 @@ func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.Cap
if err != nil {
cap.lggr.Errorf("failed to send custom message with msg: %s, err: %v", msg, err)
}
- return capabilities.CapabilityResponse{}, fmt.Errorf("submitted transaction failed: %w", err)
+ return capabilities.CapabilityResponse{}, errors.New("submitted transaction failed")
default:
cap.lggr.Debugw("Unexpected transaction status", "request", request, "transaction", txID, "status", txStatus)
}
@@ -371,3 +399,20 @@ func (cap *WriteTarget) RegisterToWorkflow(ctx context.Context, request capabili
func (cap *WriteTarget) UnregisterFromWorkflow(ctx context.Context, request capabilities.UnregisterFromWorkflowRequest) error {
return nil
}
+
+func (cap *WriteTarget) getTransmissionInfo(ctx context.Context, request Request, rawExecutionID []byte) (*TransmissionInfo, error) {
+ queryInputs := struct {
+ Receiver string
+ WorkflowExecutionID []byte
+ ReportID []byte
+ }{
+ Receiver: request.Config.Address,
+ WorkflowExecutionID: rawExecutionID,
+ ReportID: request.Inputs.SignedReport.ID,
+ }
+ var transmissionInfo TransmissionInfo
+ if err := cap.cr.GetLatestValue(ctx, cap.binding.ReadIdentifier("getTransmissionInfo"), primitives.Unconfirmed, queryInputs, &transmissionInfo); err != nil {
+ return nil, fmt.Errorf("failed to getTransmissionInfo latest value: %w", err)
+ }
+ return &transmissionInfo, nil
+}
diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go
index a702d78cb5d..6fde8387ed9 100644
--- a/core/capabilities/targets/write_target_test.go
+++ b/core/capabilities/targets/write_target_test.go
@@ -23,9 +23,20 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
)
-func TestWriteTarget(t *testing.T) {
+type testHarness struct {
+ lggr logger.Logger
+ cw *mocks.ContractWriter
+ cr *mocks.ContractValueGetter
+ config *values.Map
+ validInputs *values.Map
+ validMetadata capabilities.RequestMetadata
+ writeTarget *targets.WriteTarget
+ forwarderAddr string
+ binding types.BoundContract
+}
+
+func setup(t *testing.T) testHarness {
lggr := logger.TestLogger(t)
- ctx := context.Background()
cw := mocks.NewContractWriter(t)
cr := mocks.NewContractValueGetter(t)
@@ -85,7 +96,21 @@ func TestWriteTarget(t *testing.T) {
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) {
+ return testHarness{
+ lggr: lggr,
+ cw: cw,
+ cr: cr,
+ config: config,
+ validInputs: validInputs,
+ validMetadata: validMetadata,
+ writeTarget: writeTarget,
+ forwarderAddr: forwarderAddr,
+ binding: binding,
+ }
+}
+func TestWriteTarget(t *testing.T) {
+ th := setup(t)
+ th.cr.EXPECT().GetLatestValue(mock.Anything, th.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),
@@ -96,93 +121,96 @@ func TestWriteTarget(t *testing.T) {
Transmitter: common.HexToAddress("0x0"),
}
})
-
- cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once()
-
t.Run("succeeds with valid report", func(t *testing.T) {
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
- Config: config,
- Inputs: validInputs,
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
}
- cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Finalized, nil).Once()
+ th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Finalized, nil).Once()
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once()
- response, err2 := writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ response, err2 := th.writeTarget.Execute(ctx, req)
require.NoError(t, err2)
require.NotNil(t, response)
})
t.Run("fails when ChainWriter's SubmitTransaction returns error", func(t *testing.T) {
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
- Config: config,
- Inputs: validInputs,
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
}
- cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, forwarderAddr, mock.Anything, mock.Anything).Return(errors.New("writer error"))
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(errors.New("writer error"))
- _, err = writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err := th.writeTarget.Execute(ctx, req)
require.Error(t, err)
})
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,
+ "Address": th.forwarderAddr,
"GasLimit": 500000,
})
require.NoError(t, err2)
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
+ Metadata: th.validMetadata,
Config: configGasLimit,
- Inputs: validInputs,
+ Inputs: th.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)
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, &meta, mock.Anything).Return(types.ErrSettingTransactionGasLimitNotSupported)
- _, err2 = writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err2 = th.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,
+ "Address": th.forwarderAddr,
"GasLimit": 500000,
})
require.NoError(t, err2)
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
+ Metadata: th.validMetadata,
Config: configGasLimit,
- Inputs: validInputs,
+ Inputs: th.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)
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.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)
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, &meta, mock.Anything).Return(nil)
- configGasLimit, err = values.NewMap(map[string]any{
- "Address": forwarderAddr,
+ configGasLimit, err := values.NewMap(map[string]any{
+ "Address": th.forwarderAddr,
})
require.NoError(t, err)
req = capabilities.CapabilityRequest{
- Metadata: validMetadata,
+ Metadata: th.validMetadata,
Config: configGasLimit,
- Inputs: validInputs,
+ Inputs: th.validInputs,
}
- _, err2 = writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err2 = th.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,
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
}
- cr.EXPECT().GetLatestValue(mock.Anything, binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(errors.New("reader error"))
+ th.cr.EXPECT().GetLatestValue(mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(errors.New("reader error"))
- _, err = writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err := th.writeTarget.Execute(ctx, req)
require.Error(t, err)
})
@@ -197,32 +225,38 @@ func TestWriteTarget(t *testing.T) {
WorkflowID: "test-id",
},
Config: invalidConfig,
- Inputs: validInputs,
+ Inputs: th.validInputs,
}
- _, err2 = writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err2 = th.writeTarget.Execute(ctx, req)
require.Error(t, err2)
})
t.Run("fails with nil config", func(t *testing.T) {
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
+ Metadata: th.validMetadata,
Config: nil,
- Inputs: validInputs,
+ Inputs: th.validInputs,
}
- _, err2 := writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err2 := th.writeTarget.Execute(ctx, req)
require.Error(t, err2)
})
t.Run("fails with nil inputs", func(t *testing.T) {
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
- Config: config,
+ Metadata: th.validMetadata,
+ Config: th.config,
Inputs: nil,
}
- _, err2 := writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err2 := th.writeTarget.Execute(ctx, req)
require.Error(t, err2)
})
+}
+func TestWriteTarget_ValidateRequest(t *testing.T) {
+ th := setup(t)
tests := []struct {
name string
modifyRequest func(*capabilities.CapabilityRequest)
@@ -247,13 +281,14 @@ func TestWriteTarget(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := capabilities.CapabilityRequest{
- Metadata: validMetadata,
- Config: config,
- Inputs: validInputs,
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
}
tt.modifyRequest(&req)
- _, err := writeTarget.Execute(ctx, req)
+ ctx := testutils.Context(t)
+ _, err := th.writeTarget.Execute(ctx, req)
if tt.expectedError == "" {
require.NoError(t, err)
} else {
@@ -263,3 +298,86 @@ func TestWriteTarget(t *testing.T) {
})
}
}
+
+func TestWriteTarget_UnconfirmedTransaction(t *testing.T) {
+ t.Run("succeeds when transaction is unconfirmed but transmission succeeded ", func(t *testing.T) {
+ th := setup(t)
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once()
+ callCount := 0
+ th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) {
+ transmissionInfo := args.Get(4).(*targets.TransmissionInfo)
+ if callCount == 0 {
+ *transmissionInfo = targets.TransmissionInfo{
+ GasLimit: big.NewInt(0),
+ InvalidReceiver: false,
+ State: targets.TransmissionStateNotAttempted,
+ Success: false,
+ TransmissionId: [32]byte{},
+ Transmitter: common.HexToAddress("0x0"),
+ }
+ } else {
+ *transmissionInfo = targets.TransmissionInfo{
+ GasLimit: big.NewInt(0),
+ InvalidReceiver: false,
+ State: targets.TransmissionStateSucceeded,
+ Success: false,
+ TransmissionId: [32]byte{},
+ Transmitter: common.HexToAddress("0x0"),
+ }
+ }
+ callCount++
+ })
+ req := capabilities.CapabilityRequest{
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
+ }
+
+ th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once()
+
+ ctx := testutils.Context(t)
+ response, err2 := th.writeTarget.Execute(ctx, req)
+ require.NoError(t, err2)
+ require.NotNil(t, response)
+ })
+
+ t.Run("transaction written to the forwarder, but failed to be written to the consumer contract", func(t *testing.T) {
+ th := setup(t)
+ th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once()
+ callCount := 0
+ th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) {
+ transmissionInfo := args.Get(4).(*targets.TransmissionInfo)
+ if callCount == 0 {
+ *transmissionInfo = targets.TransmissionInfo{
+ GasLimit: big.NewInt(0),
+ InvalidReceiver: false,
+ State: targets.TransmissionStateNotAttempted,
+ Success: false,
+ TransmissionId: [32]byte{},
+ Transmitter: common.HexToAddress("0x0"),
+ }
+ } else {
+ *transmissionInfo = targets.TransmissionInfo{
+ GasLimit: big.NewInt(0),
+ InvalidReceiver: false,
+ State: targets.TransmissionStateFailed,
+ Success: false,
+ TransmissionId: [32]byte{},
+ Transmitter: common.HexToAddress("0x0"),
+ }
+ }
+ callCount++
+ })
+ req := capabilities.CapabilityRequest{
+ Metadata: th.validMetadata,
+ Config: th.config,
+ Inputs: th.validInputs,
+ }
+
+ th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once()
+ ctx := testutils.Context(t)
+ _, err2 := th.writeTarget.Execute(ctx, req)
+ require.Error(t, err2)
+ require.Contains(t, err2.Error(), "submitted transaction failed")
+ })
+}
diff --git a/core/chains/evm/forwarders/forwarder_manager_test.go b/core/chains/evm/forwarders/forwarder_manager_test.go
index a7274adf529..2eeefc5dc23 100644
--- a/core/chains/evm/forwarders/forwarder_manager_test.go
+++ b/core/chains/evm/forwarders/forwarder_manager_test.go
@@ -10,11 +10,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient/simulated"
-
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/libocr/gethwrappers2/testocr2aggregator"
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
@@ -24,27 +24,17 @@ import (
"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/generated/authorized_forwarder"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_receiver"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper"
- "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"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
- "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers"
"github.com/smartcontractkit/chainlink/v2/evm/client"
- evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
-var GetAuthorisedSendersABI = evmtypes.MustGetABI(authorized_receiver.AuthorizedReceiverABI).Methods["getAuthorizedSenders"]
-
-var SimpleOracleCallABI = evmtypes.MustGetABI(operator_wrapper.OperatorABI).Methods["getChainlinkToken"]
-
func TestFwdMgr_MaybeForwardTransaction(t *testing.T) {
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ db := testutils.NewSqlxDB(t)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
owner := testutils.MustNewSimTransactor(t)
ctx := testutils.Context(t)
@@ -111,10 +101,9 @@ func TestFwdMgr_MaybeForwardTransaction(t *testing.T) {
func TestFwdMgr_AccountUnauthorizedToForward_SkipsForwarding(t *testing.T) {
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ctx := testutils.Context(t)
- cfg := configtest.NewTestGeneralConfig(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
owner := testutils.MustNewSimTransactor(t)
b := simulated.NewBackend(types.GenesisAlloc{
owner.From: {
@@ -161,10 +150,9 @@ func TestFwdMgr_AccountUnauthorizedToForward_SkipsForwarding(t *testing.T) {
func TestFwdMgr_InvalidForwarderForOCR2FeedsStates(t *testing.T) {
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ctx := testutils.Context(t)
- cfg := configtest.NewTestGeneralConfig(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
owner := testutils.MustNewSimTransactor(t)
ec := simulated.NewBackend(types.GenesisAlloc{
owner.From: {
@@ -236,7 +224,7 @@ func TestFwdMgr_InvalidForwarderForOCR2FeedsStates(t *testing.T) {
require.ErrorIs(t, err, forwarders.ErrForwarderForEOANotFound)
require.True(t, utils.IsZero(addr))
- onchainConfig, err := testhelpers.GenerateDefaultOCR2OnchainConfig(big.NewInt(0), big.NewInt(10))
+ onchainConfig, err := median.StandardOnchainConfigCodec{}.Encode(ctx, median.OnchainConfig{Min: big.NewInt(0), Max: big.NewInt(10)})
require.NoError(t, err)
_, err = ocr2.SetConfig(owner,
diff --git a/core/chains/evm/forwarders/orm_test.go b/core/chains/evm/forwarders/orm_test.go
index fe654313aaf..9f458f86eae 100644
--- a/core/chains/evm/forwarders/orm_test.go
+++ b/core/chains/evm/forwarders/orm_test.go
@@ -11,15 +11,14 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
// Tests the atomicity of cleanup function passed to DeleteForwarder, during DELETE operation
func Test_DeleteForwarder(t *testing.T) {
t.Parallel()
- orm := NewORM(pgtest.NewSqlxDB(t))
+ orm := NewORM(testutils.NewSqlxDB(t))
addr := testutils.NewAddress()
chainID := testutils.FixtureChainID
ctx := testutils.Context(t)
diff --git a/core/chains/evm/headtracker/head_broadcaster_test.go b/core/chains/evm/headtracker/head_broadcaster_test.go
index 2292b3f482a..8fbbb66adff 100644
--- a/core/chains/evm/headtracker/head_broadcaster_test.go
+++ b/core/chains/evm/headtracker/head_broadcaster_test.go
@@ -22,10 +22,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/mocks"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
- testutils2 "github.com/smartcontractkit/chainlink/v2/evm/testutils"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
"github.com/smartcontractkit/chainlink/v2/evm/utils/big"
@@ -38,7 +37,7 @@ func waitHeadBroadcasterToStart(t *testing.T, hb types.HeadBroadcaster) {
_, unsubscribe := hb.Subscribe(subscriber)
defer unsubscribe()
- hb.BroadcastNewLongestChain(testutils2.Head(1))
+ hb.BroadcastNewLongestChain(testutils.Head(1))
g := gomega.NewWithT(t)
g.Eventually(subscriber.OnNewLongestChainCount).Should(gomega.Equal(int32(1)))
}
@@ -47,10 +46,10 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) {
t.Parallel()
g := gomega.NewWithT(t)
- evmCfg := testutils2.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
+ evmCfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
c.HeadTracker.SamplingInterval = &commonconfig.Duration{}
})
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
logger := logger.Test(t)
sub := commonmocks.NewSubscription(t)
@@ -63,7 +62,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) {
chchHeaders <- chHead
}).
Return((<-chan *evmtypes.Head)(chHead), sub, nil)
- ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils2.Head(1), nil)
+ ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(testutils.Head(1), nil)
sub.On("Unsubscribe").Return()
sub.On("Err").Return(nil)
@@ -85,7 +84,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) {
assert.Equal(t, (*evmtypes.Head)(nil), latest1)
headers := <-chchHeaders
- h := evmtypes.Head{Number: 1, Hash: utils.NewHash(), ParentHash: utils.NewHash(), EVMChainID: big.New(testutils2.FixtureChainID)}
+ h := evmtypes.Head{Number: 1, Hash: utils.NewHash(), ParentHash: utils.NewHash(), EVMChainID: big.New(testutils.FixtureChainID)}
headers <- &h
g.Eventually(checker1.OnNewLongestChainCount).Should(gomega.Equal(int32(1)))
@@ -96,7 +95,7 @@ func TestHeadBroadcaster_Subscribe(t *testing.T) {
unsubscribe1()
- headers <- &evmtypes.Head{Number: 2, Hash: utils.NewHash(), ParentHash: h.Hash, EVMChainID: big.New(testutils2.FixtureChainID)}
+ headers <- &evmtypes.Head{Number: 2, Hash: utils.NewHash(), ParentHash: h.Hash, EVMChainID: big.New(testutils.FixtureChainID)}
g.Eventually(checker2.OnNewLongestChainCount).Should(gomega.Equal(int32(1)))
}
@@ -117,25 +116,25 @@ func TestHeadBroadcaster_BroadcastNewLongestChain(t *testing.T) {
_, unsubscribe1 := broadcaster.Subscribe(subscriber1)
_, unsubscribe2 := broadcaster.Subscribe(subscriber2)
- broadcaster.BroadcastNewLongestChain(testutils2.Head(1))
+ broadcaster.BroadcastNewLongestChain(testutils.Head(1))
g.Eventually(subscriber1.OnNewLongestChainCount).Should(gomega.Equal(int32(1)))
unsubscribe1()
- broadcaster.BroadcastNewLongestChain(testutils2.Head(2))
+ broadcaster.BroadcastNewLongestChain(testutils.Head(2))
g.Eventually(subscriber2.OnNewLongestChainCount).Should(gomega.Equal(int32(2)))
unsubscribe2()
subscriber3 := &mocks.MockHeadTrackable{}
_, unsubscribe3 := broadcaster.Subscribe(subscriber3)
- broadcaster.BroadcastNewLongestChain(testutils2.Head(1))
+ broadcaster.BroadcastNewLongestChain(testutils.Head(1))
g.Eventually(subscriber3.OnNewLongestChainCount).Should(gomega.Equal(int32(1)))
unsubscribe3()
// no subscribers - shall do nothing
- broadcaster.BroadcastNewLongestChain(testutils2.Head(0))
+ broadcaster.BroadcastNewLongestChain(testutils.Head(0))
err = broadcaster.Close()
require.NoError(t, err)
@@ -154,14 +153,14 @@ func TestHeadBroadcaster_TrackableCallbackTimeout(t *testing.T) {
waitHeadBroadcasterToStart(t, broadcaster)
- slowAwaiter := testutils2.NewAwaiter()
- fastAwaiter := testutils2.NewAwaiter()
+ slowAwaiter := testutils.NewAwaiter()
+ fastAwaiter := testutils.NewAwaiter()
slow := &sleepySubscriber{awaiter: slowAwaiter, delay: commonhtrk.TrackableCallbackTimeout * 2}
fast := &sleepySubscriber{awaiter: fastAwaiter, delay: commonhtrk.TrackableCallbackTimeout / 2}
_, unsubscribe1 := broadcaster.Subscribe(slow)
_, unsubscribe2 := broadcaster.Subscribe(fast)
- broadcaster.BroadcastNewLongestChain(testutils2.Head(1))
+ broadcaster.BroadcastNewLongestChain(testutils.Head(1))
slowAwaiter.AwaitOrFail(t, tests.WaitTimeout(t))
fastAwaiter.AwaitOrFail(t, tests.WaitTimeout(t))
@@ -176,7 +175,7 @@ func TestHeadBroadcaster_TrackableCallbackTimeout(t *testing.T) {
}
type sleepySubscriber struct {
- awaiter testutils2.Awaiter
+ awaiter testutils.Awaiter
delay time.Duration
contextDone bool
}
diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go
index a02b979495c..d8c0752d427 100644
--- a/core/chains/evm/headtracker/head_saver_test.go
+++ b/core/chains/evm/headtracker/head_saver_test.go
@@ -13,7 +13,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
@@ -74,7 +73,7 @@ func configureSaver(t *testing.T, opts saverOpts) (httypes.HeadSaver, headtracke
if opts.headTrackerConfig == nil {
opts.headTrackerConfig = &headTrackerConfig{historyDepth: 6}
}
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
lggr := logger.Test(t)
htCfg := &config{finalityDepth: uint32(1)}
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go
index 680950dcb48..14fe6013f30 100644
--- a/core/chains/evm/headtracker/head_tracker_test.go
+++ b/core/chains/evm/headtracker/head_tracker_test.go
@@ -35,8 +35,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/mocks"
httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
@@ -56,7 +54,7 @@ func firstHead(t *testing.T, db *sqlx.DB) *evmtypes.Head {
func TestHeadTracker_New(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil)
// finalized
@@ -87,7 +85,7 @@ func TestHeadTracker_New(t *testing.T) {
func TestHeadTracker_MarkFinalized_MarksAndTrimsTable(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
c.HeadTracker.HistoryDepth = ptr[uint32](100)
})
@@ -137,7 +135,7 @@ func TestHeadTracker_Get(t *testing.T) {
for i := range cases {
test := cases[i]
t.Run(test.name, func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
@@ -185,7 +183,7 @@ func TestHeadTracker_Get(t *testing.T) {
func TestHeadTracker_Start_NewHeads(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
@@ -238,10 +236,10 @@ func TestHeadTracker_Start(t *testing.T) {
}
})
if opts.ORM == nil {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
opts.ORM = headtracker.NewORM(*testutils.FixtureChainID, db)
}
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
mockEth := &clienttest.MockEth{EthClient: ethClient}
sub := mockEth.NewSub(t)
ethClient.On("SubscribeToHeads", mock.Anything, mock.Anything).Return(nil, sub, nil).Maybe()
@@ -354,7 +352,7 @@ func TestHeadTracker_Start(t *testing.T) {
func TestHeadTracker_CallsHeadTrackableCallbacks(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
@@ -392,7 +390,7 @@ func TestHeadTracker_ReconnectOnError(t *testing.T) {
t.Parallel()
g := gomega.NewWithT(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
@@ -429,7 +427,7 @@ func TestHeadTracker_ResubscribeOnSubscriptionError(t *testing.T) {
t.Parallel()
g := gomega.NewWithT(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
@@ -475,7 +473,7 @@ func TestHeadTracker_ResubscribeOnSubscriptionError(t *testing.T) {
func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
@@ -540,7 +538,7 @@ func TestHeadTracker_Start_LoadsLatestChain(t *testing.T) {
func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingEnabled(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
c.FinalityDepth = ptr[uint32](50)
@@ -661,7 +659,7 @@ func assertChainWithParents(t testing.TB, blocks *blocks, startBN, endBN uint64,
func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
config := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
c.FinalityDepth = ptr[uint32](50)
@@ -798,7 +796,7 @@ 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)
+ db := testutils.NewSqlxDB(t)
return headtracker.NewORM(*testutils.FixtureChainID, db)
})
})
@@ -1156,12 +1154,12 @@ func TestHeadTracker_LatestAndFinalizedBlock(t *testing.T) {
c.FinalityDepth = ptr(opts.FinalityDepth)
})
- db := pgtest.NewSqlxDB(t)
+ db := testutils.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 := evmtest.NewEthClientMock(t)
+ ethClient := clienttest.NewClient(t)
ethClient.On("ConfiguredChainID", mock.Anything).Return(testutils.FixtureChainID, nil)
ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm)
_, err := ht.headSaver.Load(tests.Context(t), 0)
diff --git a/core/chains/evm/headtracker/orm_test.go b/core/chains/evm/headtracker/orm_test.go
index a07bfd26a1e..57ac984d95d 100644
--- a/core/chains/evm/headtracker/orm_test.go
+++ b/core/chains/evm/headtracker/orm_test.go
@@ -10,14 +10,13 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
)
func TestORM_IdempotentInsertHead(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
// Returns nil when inserting first head
@@ -41,7 +40,7 @@ func TestORM_IdempotentInsertHead(t *testing.T) {
func TestORM_TrimOldHeads(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
for i := 0; i < 10; i++ {
@@ -68,7 +67,7 @@ func TestORM_TrimOldHeads(t *testing.T) {
func TestORM_HeadByHash(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
var hash common.Hash
@@ -89,7 +88,7 @@ func TestORM_HeadByHash(t *testing.T) {
func TestORM_HeadByHash_NotFound(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
hash := testutils.Head(123).Hash
@@ -102,7 +101,7 @@ func TestORM_HeadByHash_NotFound(t *testing.T) {
func TestORM_LatestHeads_NoRows(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := headtracker.NewORM(*testutils.FixtureChainID, db)
heads, err := orm.LatestHeads(tests.Context(t), 100)
diff --git a/core/chains/evm/log/broadcaster.go b/core/chains/evm/log/broadcaster.go
index b63336a8a6c..6404ab804f3 100644
--- a/core/chains/evm/log/broadcaster.go
+++ b/core/chains/evm/log/broadcaster.go
@@ -18,8 +18,8 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
"github.com/smartcontractkit/chainlink-common/pkg/utils"
"github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
+ "github.com/smartcontractkit/chainlink-framework/chains/headtracker"
- httypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
@@ -46,7 +46,7 @@ type (
Broadcaster interface {
utils.DependentAwaiter
services.Service
- httypes.HeadTrackable
+ headtracker.HeadTrackable[*evmtypes.Head, common.Hash]
// ReplayFromBlock enqueues a replay from the provided block number. If forceBroadcast is
// set to true, the broadcaster will broadcast logs that were already marked consumed
diff --git a/core/chains/evm/log/helpers_internal_test.go b/core/chains/evm/log/helpers_internal_test.go
deleted file mode 100644
index 59a3c4aadbc..00000000000
--- a/core/chains/evm/log/helpers_internal_test.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package log
-
-import (
- "github.com/ethereum/go-ethereum/core/types"
-
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
- "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
-
- evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
- evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
-)
-
-// NewTestBroadcaster creates a broadcaster with Pause/Resume enabled.
-func NewTestBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *mailbox.Monitor) *broadcaster {
- b := NewBroadcaster(orm, ethClient, config, lggr, highestSavedHead, mailMon)
- b.testPause, b.testResume = make(chan struct{}), make(chan struct{})
- return b
-}
-
-func (b *broadcaster) ExportedAppendLogChannel(ch1, ch2 <-chan types.Log) chan types.Log {
- return b.appendLogChannel(ch1, ch2)
-}
diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go
index 0b79956db3c..59a3c4aadbc 100644
--- a/core/chains/evm/log/helpers_test.go
+++ b/core/chains/evm/log/helpers_test.go
@@ -1,405 +1,22 @@
-package log_test
+package log
import (
- "context"
- "fmt"
- "math/big"
- "sync"
- "sync/atomic"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/google/uuid"
- "github.com/onsi/gomega"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
-
- "github.com/jmoiron/sqlx"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest"
- "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
- "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/legacyevm"
- "github.com/smartcontractkit/chainlink/v2/core/config"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
- "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/testutils"
- "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/services/job"
- "github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
- "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
- evmconfig "github.com/smartcontractkit/chainlink/v2/evm/config"
- evmtestutils "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
)
-type broadcasterHelper struct {
- t *testing.T
- lb log.BroadcasterInTest
- db *sqlx.DB
- mockEth *clienttest.MockEth
- globalConfig config.AppConfig
- config evmconfig.ChainScopedConfig
-
- // each received channel corresponds to one eth subscription
- chchRawLogs chan evmtestutils.RawSub[types.Log]
- toUnsubscribe []func()
- pipelineHelper cltest.JobPipelineV2TestHelper
-}
-
-func newBroadcasterHelper(t *testing.T, blockHeight int64, timesSubscribe int, filterLogsResult []types.Log, overridesFn func(*chainlink.Config, *chainlink.Secrets)) *broadcasterHelper {
- // ensure we check before registering any mock Cleanup assertions
- testutils.SkipShortDB(t)
-
- expectedCalls := mockEthClientExpectedCalls{
- SubscribeFilterLogs: timesSubscribe,
- HeaderByNumber: 1,
- FilterLogs: 1,
- FilterLogsResult: filterLogsResult,
- }
-
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], timesSubscribe)
- mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
- helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, nil, overridesFn)
- helper.chchRawLogs = chchRawLogs
- helper.mockEth = mockEth
- return helper
-}
-
-func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, highestSeenHead *evmtypes.Head, overridesFn func(*chainlink.Config, *chainlink.Secrets)) *broadcasterHelper {
- globalConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.Database.LogQueries = ptr(true)
- finality := uint32(10)
- c.EVM[0].FinalityDepth = &finality
-
- if overridesFn != nil {
- overridesFn(c, s)
- }
- })
- config := evmtest.NewChainScopedConfig(t, globalConfig)
- lggr := logger.Test(t)
- mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t))
-
- db := pgtest.NewSqlxDB(t)
- orm := log.NewORM(db, cltest.FixtureChainID)
- lb := log.NewTestBroadcaster(orm, ethClient, config.EVM(), lggr, highestSeenHead, mailMon)
- kst := cltest.NewKeyStore(t, db)
-
- chainsAndConfig := evmtest.NewLegacyChainsAndConfig(t, evmtest.TestChainOpts{
- Client: ethClient,
- GeneralConfig: globalConfig,
- DatabaseConfig: globalConfig.Database(),
- FeatureConfig: globalConfig.Feature(),
- ListenerConfig: globalConfig.Database().Listener(),
- DB: db,
- KeyStore: kst.Eth(),
- LogBroadcaster: &log.NullBroadcaster{},
- MailMon: mailMon,
- })
-
- m := make(map[string]legacyevm.Chain)
- for _, r := range chainsAndConfig.Slice() {
- m[r.ID().String()] = r
- }
-
- legacyChains := chainsAndConfig.NewLegacyChains()
- pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), legacyChains, db, kst, nil, nil)
-
- return &broadcasterHelper{
- t: t,
- lb: lb,
- db: db,
- globalConfig: globalConfig,
- config: config,
- pipelineHelper: pipelineHelper,
- toUnsubscribe: make([]func(), 0),
- }
-}
-
-func (helper *broadcasterHelper) start() {
- err := helper.lb.Start(testutils.Context(helper.t))
- require.NoError(helper.t, err)
-}
-
-func (helper *broadcasterHelper) register(listener log.Listener, contract log.AbigenContract, numConfirmations uint32) {
- logs := []generated.AbigenLog{
- flux_aggregator_wrapper.FluxAggregatorNewRound{},
- flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{},
- }
- helper.registerWithTopics(listener, contract, logs, numConfirmations)
-}
-
-func (helper *broadcasterHelper) registerWithTopics(listener log.Listener, contract log.AbigenContract, logs []generated.AbigenLog, numConfirmations uint32) {
- logsWithTopics := make(map[common.Hash][][]log.Topic)
- for _, log := range logs {
- logsWithTopics[log.Topic()] = nil
- }
- helper.registerWithTopicValues(listener, contract, numConfirmations, logsWithTopics)
-}
-
-func (helper *broadcasterHelper) registerWithTopicValues(listener log.Listener, contract log.AbigenContract, numConfirmations uint32,
- topics map[common.Hash][][]log.Topic) {
- unsubscribe := helper.lb.Register(listener, log.ListenerOpts{
- Contract: contract.Address(),
- ParseLog: contract.ParseLog,
- LogsWithTopics: topics,
- MinIncomingConfirmations: numConfirmations,
- })
-
- helper.toUnsubscribe = append(helper.toUnsubscribe, unsubscribe)
-}
-
-func (helper *broadcasterHelper) requireBroadcastCount(expectedCount int) {
- helper.t.Helper()
- g := gomega.NewGomegaWithT(helper.t)
-
- comparisonFunc := func() (int, error) {
- var count struct{ Count int }
- err := helper.db.Get(&count, `SELECT count(*) FROM log_broadcasts`)
- return count.Count, err
- }
-
- g.Eventually(comparisonFunc, testutils.WaitTimeout(helper.t), time.Second).Should(gomega.Equal(expectedCount))
- g.Consistently(comparisonFunc, 1*time.Second, 200*time.Millisecond).Should(gomega.Equal(expectedCount))
-}
-
-func (helper *broadcasterHelper) unsubscribeAll() {
- for _, unsubscribe := range helper.toUnsubscribe {
- unsubscribe()
- }
- time.Sleep(100 * time.Millisecond)
-}
-func (helper *broadcasterHelper) stop() {
- err := helper.lb.Close()
- assert.NoError(helper.t, err)
-}
-
-func newMockContract(t *testing.T) *logmocks.AbigenContract {
- addr := testutils.NewAddress()
- contract := logmocks.NewAbigenContract(t)
- contract.On("Address").Return(addr).Maybe()
- return contract
-}
-
-type logOnBlock struct {
- logBlockNumber uint64
- blockNumber uint64
- blockHash common.Hash
-}
-
-func (l logOnBlock) String() string {
- return fmt.Sprintf("blockInfo(log:%v received on: %v %s)", l.logBlockNumber, l.blockNumber, l.blockHash)
-}
-
-type received struct {
- uniqueLogs []types.Log
- logs []types.Log
- broadcasts []log.Broadcast
- sync.Mutex
-}
-
-func newReceived(logs []types.Log) *received {
- var rec received
- rec.logs = logs
- rec.uniqueLogs = logs
- return &rec
+// NewTestBroadcaster creates a broadcaster with Pause/Resume enabled.
+func NewTestBroadcaster(orm ORM, ethClient evmclient.Client, config Config, lggr logger.Logger, highestSavedHead *evmtypes.Head, mailMon *mailbox.Monitor) *broadcaster {
+ b := NewBroadcaster(orm, ethClient, config, lggr, highestSavedHead, mailMon)
+ b.testPause, b.testResume = make(chan struct{}), make(chan struct{})
+ return b
}
-func (rec *received) getLogs() []types.Log {
- rec.Lock()
- defer rec.Unlock()
- r := make([]types.Log, len(rec.logs))
- copy(r, rec.logs)
- return r
-}
-
-func (rec *received) getUniqueLogs() []types.Log {
- rec.Lock()
- defer rec.Unlock()
- r := make([]types.Log, len(rec.uniqueLogs))
- copy(r, rec.uniqueLogs)
- return r
-}
-
-func (rec *received) logsOnBlocks() []logOnBlock {
- rec.Lock()
- defer rec.Unlock()
- var blocks []logOnBlock
- for _, broadcast := range rec.broadcasts {
- blocks = append(blocks, logOnBlock{
- logBlockNumber: broadcast.RawLog().BlockNumber,
- blockNumber: broadcast.LatestBlockNumber(),
- blockHash: broadcast.LatestBlockHash(),
- })
- }
- return blocks
-}
-
-type simpleLogListener struct {
- name string
- lggr logger.SugaredLogger
- received *received
- t *testing.T
- db *sqlx.DB
- jobID int32
- skipMarkingConsumed atomic.Bool
-}
-
-func (helper *broadcasterHelper) newLogListenerWithJob(name string) *simpleLogListener {
- t := helper.t
- db := helper.db
- jb := &job.Job{
- Type: job.Cron,
- SchemaVersion: 1,
- CronSpec: &job.CronSpec{CronSchedule: "@every 1s"},
- PipelineSpec: &pipeline.Spec{},
- ExternalJobID: uuid.New(),
- }
- err := helper.pipelineHelper.Jrm.CreateJob(testutils.Context(t), jb)
- require.NoError(t, err)
-
- var rec received
- return &simpleLogListener{
- db: db,
- lggr: logger.Sugared(logger.Test(t)),
- name: name,
- received: &rec,
- t: t,
- jobID: jb.ID,
- }
-}
-
-func (listener *simpleLogListener) SkipMarkingConsumed(skip bool) {
- listener.skipMarkingConsumed.Store(skip)
-}
-
-func (listener *simpleLogListener) HandleLog(ctx context.Context, lb log.Broadcast) {
- listener.received.Lock()
- defer listener.received.Unlock()
- listener.lggr.Tracef("Listener %v HandleLog for block %v %v received at %v %v", listener.name, lb.RawLog().BlockNumber, lb.RawLog().BlockHash, lb.LatestBlockNumber(), lb.LatestBlockHash())
-
- listener.received.logs = append(listener.received.logs, lb.RawLog())
- listener.received.broadcasts = append(listener.received.broadcasts, lb)
- consumed := listener.handleLogBroadcast(ctx, lb)
-
- if !consumed {
- listener.received.uniqueLogs = append(listener.received.uniqueLogs, lb.RawLog())
- } else {
- listener.lggr.Warnf("Listener %v: Log was already consumed!", listener.name)
- }
-}
-
-func (listener *simpleLogListener) JobID() int32 {
- return listener.jobID
-}
-
-func (listener *simpleLogListener) getUniqueLogs() []types.Log {
- return listener.received.getUniqueLogs()
-}
-
-func (listener *simpleLogListener) getUniqueLogsBlockNumbers() []uint64 {
- var blockNums []uint64
- for _, uniqueLog := range listener.received.getUniqueLogs() {
- blockNums = append(blockNums, uniqueLog.BlockNumber)
- }
- return blockNums
-}
-
-func (listener *simpleLogListener) requireAllReceived(t *testing.T, expectedState *received) {
- received := listener.received
- defer func() { assert.EqualValues(t, expectedState.getUniqueLogs(), received.getUniqueLogs()) }()
- require.Eventually(t, func() bool {
- return len(received.getUniqueLogs()) == len(expectedState.getUniqueLogs())
- }, testutils.WaitTimeout(t), time.Second, "len(received.uniqueLogs): %v is not equal len(expectedState.uniqueLogs): %v", len(received.getUniqueLogs()), len(expectedState.getUniqueLogs()))
-}
-
-func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb log.Broadcast) bool {
- t := listener.t
- consumed, err := listener.WasAlreadyConsumed(ctx, lb)
- if !assert.NoError(t, err) {
- return false
- }
- if !consumed && !listener.skipMarkingConsumed.Load() {
- err = listener.MarkConsumed(ctx, lb)
- if assert.NoError(t, err) {
- consumed2, err := listener.WasAlreadyConsumed(ctx, lb)
- if assert.NoError(t, err) {
- assert.True(t, consumed2)
- }
- }
- }
- return consumed
-}
-
-func (listener *simpleLogListener) WasAlreadyConsumed(ctx context.Context, broadcast log.Broadcast) (bool, error) {
- return log.NewORM(listener.db, cltest.FixtureChainID).WasBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().Index, listener.jobID)
-}
-
-func (listener *simpleLogListener) MarkConsumed(ctx context.Context, broadcast log.Broadcast) error {
- return log.NewORM(listener.db, cltest.FixtureChainID).MarkBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().BlockNumber, broadcast.RawLog().Index, listener.jobID)
-}
-
-type mockListener struct {
- jobID int32
-}
-
-func (l *mockListener) JobID() int32 { return l.jobID }
-func (l *mockListener) HandleLog(context.Context, log.Broadcast) {}
-
-type mockEthClientExpectedCalls struct {
- SubscribeFilterLogs int
- HeaderByNumber int
- FilterLogs int
-
- FilterLogsResult []types.Log
-}
-
-func newMockEthClient(t *testing.T, chchRawLogs chan<- evmtestutils.RawSub[types.Log], blockHeight int64, expectedCalls mockEthClientExpectedCalls) *clienttest.MockEth {
- ethClient := clienttest.NewClient(t)
- mockEth := &clienttest.MockEth{EthClient: ethClient}
- mockEth.EthClient.On("ConfiguredChainID", mock.Anything).Return(&cltest.FixtureChainID)
- mockEth.EthClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything).
- Return(
- func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription {
- sub := mockEth.NewSub(t)
- chchRawLogs <- evmtestutils.NewRawSub(ch, sub.Err())
- return sub
- },
- func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) error {
- return nil
- },
- ).
- Times(expectedCalls.SubscribeFilterLogs)
-
- mockEth.EthClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).
- Return(&evmtypes.Head{Number: blockHeight}, nil).
- Times(expectedCalls.HeaderByNumber)
-
- if expectedCalls.FilterLogs > 0 {
- mockEth.EthClient.On("FilterLogs", mock.Anything, mock.Anything).
- Run(func(args mock.Arguments) {
- filterQuery := args.Get(1).(ethereum.FilterQuery)
- fromBlock := filterQuery.FromBlock.Int64()
- toBlock := filterQuery.ToBlock.Int64()
- if mockEth.CheckFilterLogs != nil {
- mockEth.CheckFilterLogs(fromBlock, toBlock)
- }
- }).
- Return(expectedCalls.FilterLogsResult, nil).
- Times(expectedCalls.FilterLogs)
- }
-
- return mockEth
+func (b *broadcaster) ExportedAppendLogChannel(ch1, ch2 <-chan types.Log) chan types.Log {
+ return b.appendLogChannel(ch1, ch2)
}
diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go
index 1f730cb46c5..4cd5024b581 100644
--- a/core/chains/evm/log/integration_test.go
+++ b/core/chains/evm/log/integration_test.go
@@ -2,8 +2,10 @@ package log_test
import (
"context"
+ "fmt"
"math/big"
"slices"
+ "sync"
"sync/atomic"
"testing"
"time"
@@ -11,6 +13,8 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/google/uuid"
+ "github.com/jmoiron/sqlx"
"github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -22,14 +26,20 @@ import (
"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/legacyevm"
+ "github.com/smartcontractkit/chainlink/v2/core/config"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
"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/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
+ "github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
+ evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
- evmtestutils "github.com/smartcontractkit/chainlink/v2/evm/testutils"
+ evmconfig "github.com/smartcontractkit/chainlink/v2/evm/config"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
)
@@ -82,12 +92,12 @@ func TestBroadcaster_ResubscribesOnAddOrRemoveContract(t *testing.T) {
FilterLogs: backfillTimes,
}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, cltest.Head(lastStoredBlockHeight), nil)
helper.mockEth = mockEth
- blockBackfillDepth := helper.config.EVM().BlockBackfillDepth()
+ blockBackfillDepth := helper.config.BlockBackfillDepth()
var backfillCount atomic.Int64
@@ -148,7 +158,7 @@ func TestBroadcaster_BackfillOnNodeStartAndOnReplay(t *testing.T) {
FilterLogs: 2,
}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, cltest.Head(lastStoredBlockHeight), nil)
helper.mockEth = mockEth
@@ -163,7 +173,7 @@ func TestBroadcaster_BackfillOnNodeStartAndOnReplay(t *testing.T) {
listener2 := helper.newLogListenerWithJob("two")
helper.register(listener2, newMockContract(t), uint32(2))
- blockBackfillDepth := helper.config.EVM().BlockBackfillDepth()
+ blockBackfillDepth := helper.config.BlockBackfillDepth()
// the first backfill should use the height of last head saved to the db,
// minus maxNumConfirmations of subscribers and minus blockBackfillDepth
@@ -205,7 +215,7 @@ func TestBroadcaster_ReplaysLogs(t *testing.T) {
blocks.LogOnBlockNum(7, contract.Address()),
}
- mockEth := newMockEthClient(t, make(chan evmtestutils.RawSub[types.Log], 4), blockHeight, mockEthClientExpectedCalls{
+ mockEth := newMockEthClient(t, make(chan testutils.RawSub[types.Log], 4), blockHeight, mockEthClientExpectedCalls{
FilterLogs: 4,
FilterLogsResult: sentLogs,
})
@@ -410,7 +420,7 @@ func TestBroadcaster_ShallowBackfillOnNodeStart(t *testing.T) {
FilterLogs: backfillTimes,
}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, cltest.Head(lastStoredBlockHeight), func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].BlockBackfillSkip = ptr(true)
@@ -460,14 +470,14 @@ func TestBroadcaster_BackfillInBatches(t *testing.T) {
FilterLogs: expectedBatches,
}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, cltest.Head(lastStoredBlockHeight), func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].LogBackfillBatchSize = ptr(uint32(batchSize))
})
helper.mockEth = mockEth
- blockBackfillDepth := helper.config.EVM().BlockBackfillDepth()
+ blockBackfillDepth := helper.config.BlockBackfillDepth()
var backfillCount atomic.Int64
@@ -533,7 +543,7 @@ func TestBroadcaster_BackfillALargeNumberOfLogs(t *testing.T) {
FilterLogsResult: backfilledLogs,
}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, cltest.Head(lastStoredBlockHeight), func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].LogBackfillBatchSize = ptr(batchSize)
@@ -1014,7 +1024,7 @@ func TestBroadcaster_Register_ResubscribesToMostRecentlySeenBlock(t *testing.T)
contract2 = newMockContract(t)
)
mockEth := &clienttest.MockEth{EthClient: ethClient}
- chchRawLogs := make(chan evmtestutils.RawSub[types.Log], backfillTimes)
+ chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes)
chStarted := make(chan struct{})
ethClient.On("ConfiguredChainID", mock.Anything).Return(&cltest.FixtureChainID)
ethClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything).
@@ -1022,7 +1032,7 @@ func TestBroadcaster_Register_ResubscribesToMostRecentlySeenBlock(t *testing.T)
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription {
defer close(chStarted)
sub := mockEth.NewSub(t)
- chchRawLogs <- evmtestutils.NewRawSub(ch, sub.Err())
+ chchRawLogs <- testutils.NewRawSub(ch, sub.Err())
return sub
},
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) error {
@@ -1035,7 +1045,7 @@ func TestBroadcaster_Register_ResubscribesToMostRecentlySeenBlock(t *testing.T)
Return(
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription {
sub := mockEth.NewSub(t)
- chchRawLogs <- evmtestutils.NewRawSub(ch, sub.Err())
+ chchRawLogs <- testutils.NewRawSub(ch, sub.Err())
return sub
},
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) error {
@@ -1326,7 +1336,7 @@ func TestBroadcaster_AppendLogChannel(t *testing.T) {
ch2 := make(chan types.Log)
ch3 := make(chan types.Log)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
mailMon := servicetest.RunHealthy(t, mailboxtest.NewMonitor(t))
lb := log.NewBroadcaster(nil, ethClient, nil, logger.Test(t), nil, mailMon)
chCombined := lb.ExportedAppendLogChannel(ch1, ch2)
@@ -1533,12 +1543,12 @@ func TestBroadcaster_BroadcastsWithZeroConfirmations(t *testing.T) {
ethClient := clienttest.NewClient(t)
mockEth := &clienttest.MockEth{EthClient: ethClient}
ethClient.On("ConfiguredChainID").Return(big.NewInt(0)).Maybe()
- logsChCh := make(chan evmtestutils.RawSub[types.Log])
+ logsChCh := make(chan testutils.RawSub[types.Log])
ethClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything).
Return(
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription {
sub := mockEth.NewSub(t)
- logsChCh <- evmtestutils.NewRawSub(ch, sub.Err())
+ logsChCh <- testutils.NewRawSub(ch, sub.Err())
return sub
},
func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) error {
@@ -1633,3 +1643,355 @@ func TestBroadcaster_BroadcastsWithZeroConfirmations(t *testing.T) {
}
func ptr[T any](t T) *T { return &t }
+
+func newBroadcasterHelper(t *testing.T, blockHeight int64, timesSubscribe int, filterLogsResult []types.Log, overridesFn func(*chainlink.Config, *chainlink.Secrets)) *broadcasterHelper {
+ // ensure we check before registering any mock Cleanup assertions
+ testutils.SkipShortDB(t)
+
+ expectedCalls := mockEthClientExpectedCalls{
+ SubscribeFilterLogs: timesSubscribe,
+ HeaderByNumber: 1,
+ FilterLogs: 1,
+ FilterLogsResult: filterLogsResult,
+ }
+
+ chchRawLogs := make(chan testutils.RawSub[types.Log], timesSubscribe)
+ mockEth := newMockEthClient(t, chchRawLogs, blockHeight, expectedCalls)
+ helper := newBroadcasterHelperWithEthClient(t, mockEth.EthClient, nil, overridesFn)
+ helper.chchRawLogs = chchRawLogs
+ helper.mockEth = mockEth
+ return helper
+}
+
+func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, highestSeenHead *evmtypes.Head, overridesFn func(*chainlink.Config, *chainlink.Secrets)) *broadcasterHelper {
+ globalConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ c.Database.LogQueries = ptr(true)
+ finality := uint32(10)
+ c.EVM[0].FinalityDepth = &finality
+
+ if overridesFn != nil {
+ overridesFn(c, s)
+ }
+ })
+ config := evmtest.NewChainScopedConfig(t, globalConfig).EVM()
+ lggr := logger.Test(t)
+ mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t))
+
+ db := testutils.NewSqlxDB(t)
+ orm := log.NewORM(db, cltest.FixtureChainID)
+ lb := log.NewTestBroadcaster(orm, ethClient, config, lggr, highestSeenHead, mailMon)
+ kst := cltest.NewKeyStore(t, db)
+
+ chainsAndConfig := evmtest.NewLegacyChainsAndConfig(t, evmtest.TestChainOpts{
+ Client: ethClient,
+ ChainConfigs: globalConfig.EVMConfigs(),
+ DatabaseConfig: globalConfig.Database(),
+ FeatureConfig: globalConfig.Feature(),
+ ListenerConfig: globalConfig.Database().Listener(),
+ DB: db,
+ KeyStore: kst.Eth(),
+ LogBroadcaster: &log.NullBroadcaster{},
+ MailMon: mailMon,
+ })
+
+ m := make(map[string]legacyevm.Chain)
+ for _, r := range chainsAndConfig.Slice() {
+ m[r.ID().String()] = r
+ }
+
+ legacyChains := chainsAndConfig.NewLegacyChains()
+ pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), legacyChains, db, kst, nil, nil)
+
+ return &broadcasterHelper{
+ t: t,
+ lb: lb,
+ db: db,
+ globalConfig: globalConfig,
+ config: config,
+ pipelineHelper: pipelineHelper,
+ toUnsubscribe: make([]func(), 0),
+ }
+}
+
+type broadcasterHelper struct {
+ t *testing.T
+ lb log.BroadcasterInTest
+ db *sqlx.DB
+ mockEth *clienttest.MockEth
+ globalConfig config.AppConfig
+ config evmconfig.EVM
+
+ // each received channel corresponds to one eth subscription
+ chchRawLogs chan testutils.RawSub[types.Log]
+ toUnsubscribe []func()
+ pipelineHelper cltest.JobPipelineV2TestHelper
+}
+
+func (helper *broadcasterHelper) start() {
+ err := helper.lb.Start(testutils.Context(helper.t))
+ require.NoError(helper.t, err)
+}
+
+func (helper *broadcasterHelper) register(listener log.Listener, contract log.AbigenContract, numConfirmations uint32) {
+ logs := []generated.AbigenLog{
+ flux_aggregator_wrapper.FluxAggregatorNewRound{},
+ flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{},
+ }
+ helper.registerWithTopics(listener, contract, logs, numConfirmations)
+}
+
+func (helper *broadcasterHelper) registerWithTopics(listener log.Listener, contract log.AbigenContract, logs []generated.AbigenLog, numConfirmations uint32) {
+ logsWithTopics := make(map[common.Hash][][]log.Topic)
+ for _, log := range logs {
+ logsWithTopics[log.Topic()] = nil
+ }
+ helper.registerWithTopicValues(listener, contract, numConfirmations, logsWithTopics)
+}
+
+func (helper *broadcasterHelper) registerWithTopicValues(listener log.Listener, contract log.AbigenContract, numConfirmations uint32,
+ topics map[common.Hash][][]log.Topic) {
+ unsubscribe := helper.lb.Register(listener, log.ListenerOpts{
+ Contract: contract.Address(),
+ ParseLog: contract.ParseLog,
+ LogsWithTopics: topics,
+ MinIncomingConfirmations: numConfirmations,
+ })
+
+ helper.toUnsubscribe = append(helper.toUnsubscribe, unsubscribe)
+}
+
+func (helper *broadcasterHelper) requireBroadcastCount(expectedCount int) {
+ helper.t.Helper()
+ g := gomega.NewGomegaWithT(helper.t)
+
+ comparisonFunc := func() (int, error) {
+ var count struct{ Count int }
+ err := helper.db.Get(&count, `SELECT count(*) FROM log_broadcasts`)
+ return count.Count, err
+ }
+
+ g.Eventually(comparisonFunc, testutils.WaitTimeout(helper.t), time.Second).Should(gomega.Equal(expectedCount))
+ g.Consistently(comparisonFunc, 1*time.Second, 200*time.Millisecond).Should(gomega.Equal(expectedCount))
+}
+
+func (helper *broadcasterHelper) unsubscribeAll() {
+ for _, unsubscribe := range helper.toUnsubscribe {
+ unsubscribe()
+ }
+ time.Sleep(100 * time.Millisecond)
+}
+func (helper *broadcasterHelper) stop() {
+ err := helper.lb.Close()
+ assert.NoError(helper.t, err)
+}
+
+func newMockContract(t *testing.T) *logmocks.AbigenContract {
+ addr := testutils.NewAddress()
+ contract := logmocks.NewAbigenContract(t)
+ contract.On("Address").Return(addr).Maybe()
+ return contract
+}
+
+type logOnBlock struct {
+ logBlockNumber uint64
+ blockNumber uint64
+ blockHash common.Hash
+}
+
+func (l logOnBlock) String() string {
+ return fmt.Sprintf("blockInfo(log:%v received on: %v %s)", l.logBlockNumber, l.blockNumber, l.blockHash)
+}
+
+type received struct {
+ uniqueLogs []types.Log
+ logs []types.Log
+ broadcasts []log.Broadcast
+ sync.Mutex
+}
+
+func newReceived(logs []types.Log) *received {
+ var rec received
+ rec.logs = logs
+ rec.uniqueLogs = logs
+ return &rec
+}
+
+func (rec *received) getLogs() []types.Log {
+ rec.Lock()
+ defer rec.Unlock()
+ r := make([]types.Log, len(rec.logs))
+ copy(r, rec.logs)
+ return r
+}
+
+func (rec *received) getUniqueLogs() []types.Log {
+ rec.Lock()
+ defer rec.Unlock()
+ r := make([]types.Log, len(rec.uniqueLogs))
+ copy(r, rec.uniqueLogs)
+ return r
+}
+
+func (rec *received) logsOnBlocks() []logOnBlock {
+ rec.Lock()
+ defer rec.Unlock()
+ var blocks []logOnBlock
+ for _, broadcast := range rec.broadcasts {
+ blocks = append(blocks, logOnBlock{
+ logBlockNumber: broadcast.RawLog().BlockNumber,
+ blockNumber: broadcast.LatestBlockNumber(),
+ blockHash: broadcast.LatestBlockHash(),
+ })
+ }
+ return blocks
+}
+
+type simpleLogListener struct {
+ name string
+ lggr logger.SugaredLogger
+ received *received
+ t *testing.T
+ db *sqlx.DB
+ jobID int32
+ skipMarkingConsumed atomic.Bool
+}
+
+func (helper *broadcasterHelper) newLogListenerWithJob(name string) *simpleLogListener {
+ t := helper.t
+ db := helper.db
+ jb := &job.Job{
+ Type: job.Cron,
+ SchemaVersion: 1,
+ CronSpec: &job.CronSpec{CronSchedule: "@every 1s"},
+ PipelineSpec: &pipeline.Spec{},
+ ExternalJobID: uuid.New(),
+ }
+ err := helper.pipelineHelper.Jrm.CreateJob(testutils.Context(t), jb)
+ require.NoError(t, err)
+
+ var rec received
+ return &simpleLogListener{
+ db: db,
+ lggr: logger.Sugared(logger.Test(t)),
+ name: name,
+ received: &rec,
+ t: t,
+ jobID: jb.ID,
+ }
+}
+
+func (listener *simpleLogListener) SkipMarkingConsumed(skip bool) {
+ listener.skipMarkingConsumed.Store(skip)
+}
+
+func (listener *simpleLogListener) HandleLog(ctx context.Context, lb log.Broadcast) {
+ listener.received.Lock()
+ defer listener.received.Unlock()
+ listener.lggr.Tracef("Listener %v HandleLog for block %v %v received at %v %v", listener.name, lb.RawLog().BlockNumber, lb.RawLog().BlockHash, lb.LatestBlockNumber(), lb.LatestBlockHash())
+
+ listener.received.logs = append(listener.received.logs, lb.RawLog())
+ listener.received.broadcasts = append(listener.received.broadcasts, lb)
+ consumed := listener.handleLogBroadcast(ctx, lb)
+
+ if !consumed {
+ listener.received.uniqueLogs = append(listener.received.uniqueLogs, lb.RawLog())
+ } else {
+ listener.lggr.Warnf("Listener %v: Log was already consumed!", listener.name)
+ }
+}
+
+func (listener *simpleLogListener) JobID() int32 {
+ return listener.jobID
+}
+
+func (listener *simpleLogListener) getUniqueLogs() []types.Log {
+ return listener.received.getUniqueLogs()
+}
+
+func (listener *simpleLogListener) getUniqueLogsBlockNumbers() []uint64 {
+ var blockNums []uint64
+ for _, uniqueLog := range listener.received.getUniqueLogs() {
+ blockNums = append(blockNums, uniqueLog.BlockNumber)
+ }
+ return blockNums
+}
+
+func (listener *simpleLogListener) requireAllReceived(t *testing.T, expectedState *received) {
+ received := listener.received
+ defer func() { assert.EqualValues(t, expectedState.getUniqueLogs(), received.getUniqueLogs()) }()
+ require.Eventually(t, func() bool {
+ return len(received.getUniqueLogs()) == len(expectedState.getUniqueLogs())
+ }, testutils.WaitTimeout(t), time.Second, "len(received.uniqueLogs): %v is not equal len(expectedState.uniqueLogs): %v", len(received.getUniqueLogs()), len(expectedState.getUniqueLogs()))
+}
+
+func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb log.Broadcast) bool {
+ t := listener.t
+ consumed, err := listener.WasAlreadyConsumed(ctx, lb)
+ if !assert.NoError(t, err) {
+ return false
+ }
+ if !consumed && !listener.skipMarkingConsumed.Load() {
+ err = listener.MarkConsumed(ctx, lb)
+ if assert.NoError(t, err) {
+ consumed2, err := listener.WasAlreadyConsumed(ctx, lb)
+ if assert.NoError(t, err) {
+ assert.True(t, consumed2)
+ }
+ }
+ }
+ return consumed
+}
+
+func (listener *simpleLogListener) WasAlreadyConsumed(ctx context.Context, broadcast log.Broadcast) (bool, error) {
+ return log.NewORM(listener.db, cltest.FixtureChainID).WasBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().Index, listener.jobID)
+}
+
+func (listener *simpleLogListener) MarkConsumed(ctx context.Context, broadcast log.Broadcast) error {
+ return log.NewORM(listener.db, cltest.FixtureChainID).MarkBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().BlockNumber, broadcast.RawLog().Index, listener.jobID)
+}
+
+type mockEthClientExpectedCalls struct {
+ SubscribeFilterLogs int
+ HeaderByNumber int
+ FilterLogs int
+
+ FilterLogsResult []types.Log
+}
+
+func newMockEthClient(t *testing.T, chchRawLogs chan<- testutils.RawSub[types.Log], blockHeight int64, expectedCalls mockEthClientExpectedCalls) *clienttest.MockEth {
+ ethClient := clienttest.NewClient(t)
+ mockEth := &clienttest.MockEth{EthClient: ethClient}
+ mockEth.EthClient.On("ConfiguredChainID", mock.Anything).Return(&cltest.FixtureChainID)
+ mockEth.EthClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything).
+ Return(
+ func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription {
+ sub := mockEth.NewSub(t)
+ chchRawLogs <- testutils.NewRawSub(ch, sub.Err())
+ return sub
+ },
+ func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) error {
+ return nil
+ },
+ ).
+ Times(expectedCalls.SubscribeFilterLogs)
+
+ mockEth.EthClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).
+ Return(&evmtypes.Head{Number: blockHeight}, nil).
+ Times(expectedCalls.HeaderByNumber)
+
+ if expectedCalls.FilterLogs > 0 {
+ mockEth.EthClient.On("FilterLogs", mock.Anything, mock.Anything).
+ Run(func(args mock.Arguments) {
+ filterQuery := args.Get(1).(ethereum.FilterQuery)
+ fromBlock := filterQuery.FromBlock.Int64()
+ toBlock := filterQuery.ToBlock.Int64()
+ if mockEth.CheckFilterLogs != nil {
+ mockEth.CheckFilterLogs(fromBlock, toBlock)
+ }
+ }).
+ Return(expectedCalls.FilterLogsResult, nil).
+ Times(expectedCalls.FilterLogs)
+ }
+
+ return mockEth
+}
diff --git a/core/chains/evm/log/orm_test.go b/core/chains/evm/log/orm_test.go
index dc3611e8e6f..be8cbaa4b5a 100644
--- a/core/chains/evm/log/orm_test.go
+++ b/core/chains/evm/log/orm_test.go
@@ -1,6 +1,7 @@
package log_test
import (
+ "context"
"math/big"
"math/rand"
"testing"
@@ -12,12 +13,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/log"
"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/evm/testutils"
)
func TestORM_broadcasts(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
orm := log.NewORM(db, cltest.FixtureChainID)
@@ -80,7 +80,7 @@ func TestORM_broadcasts(t *testing.T) {
func TestORM_pending(t *testing.T) {
ctx := testutils.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := log.NewORM(db, cltest.FixtureChainID)
num, err := orm.GetPendingMinBlock(ctx)
@@ -105,7 +105,7 @@ func TestORM_pending(t *testing.T) {
func TestORM_MarkUnconsumed(t *testing.T) {
ctx := testutils.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
orm := log.NewORM(db, cltest.FixtureChainID)
@@ -202,7 +202,7 @@ func TestORM_Reinitialize(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ctx := testutils.Context(t)
orm := log.NewORM(db, cltest.FixtureChainID)
@@ -239,3 +239,10 @@ func TestORM_Reinitialize(t *testing.T) {
})
}
}
+
+type mockListener struct {
+ jobID int32
+}
+
+func (l *mockListener) JobID() int32 { return l.jobID }
+func (l *mockListener) HandleLog(context.Context, log.Broadcast) {}
diff --git a/core/chains/evm/log/pool_test.go b/core/chains/evm/log/pool_test.go
index c4789f5acd4..50b16f51954 100644
--- a/core/chains/evm/log/pool_test.go
+++ b/core/chains/evm/log/pool_test.go
@@ -4,13 +4,12 @@ import (
"math/big"
"testing"
- "github.com/stretchr/testify/assert"
-
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
)
var (
diff --git a/core/chains/evm/log/registrations_test.go b/core/chains/evm/log/registrations_test.go
index 2ef909ed7bd..d97a7b399d5 100644
--- a/core/chains/evm/log/registrations_test.go
+++ b/core/chains/evm/log/registrations_test.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
)
diff --git a/core/chains/evm/logpoller/helper_test.go b/core/chains/evm/logpoller/helper_test.go
index a3af650c1a3..5f3cc719606 100644
--- a/core/chains/evm/logpoller/helper_test.go
+++ b/core/chains/evm/logpoller/helper_test.go
@@ -23,10 +23,9 @@ import (
"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/shared/generated/log_emitter"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/config/chaintype"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
)
@@ -94,7 +93,7 @@ func SetupTH(t testing.TB, opts logpoller.Opts) TestHarness {
lggr := logger.Test(t)
chainID := testutils.NewRandomEVMChainID()
chainID2 := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
o := logpoller.NewORM(chainID, db, lggr)
o2 := logpoller.NewORM(chainID2, db, lggr)
diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go
index 589d45d328c..3f88706db85 100644
--- a/core/chains/evm/logpoller/log_poller_internal_test.go
+++ b/core/chains/evm/logpoller/log_poller_internal_test.go
@@ -30,9 +30,8 @@ import (
htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
)
@@ -64,7 +63,7 @@ func TestLogPoller_RegisterFilter(t *testing.T) {
lggr, observedLogs := logger.TestObserved(t, zapcore.WarnLevel)
chainID := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ctx := testutils.Context(t)
orm := NewORM(chainID, db, lggr)
@@ -208,7 +207,7 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) {
addr := common.HexToAddress("0x2ab9a2dc53736b361b72d900cdf9f78f9406fbbc")
lggr, observedLogs := logger.TestObserved(t, zapcore.WarnLevel)
chainID := testutils.FixtureChainID
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := NewORM(chainID, db, lggr)
latestBlock := int64(4)
const finalityDepth = 2
@@ -302,7 +301,7 @@ func TestLogPoller_Replay(t *testing.T) {
lggr, observedLogs := logger.TestObserved(t, zapcore.ErrorLevel)
chainID := testutils.FixtureChainID
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := NewORM(chainID, db, lggr)
var head atomic.Pointer[evmtypes.Head]
@@ -606,7 +605,7 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) {
func Test_FetchBlocks(t *testing.T) {
lggr := logger.Test(t)
chainID := testutils.FixtureChainID
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := NewORM(chainID, db, lggr)
ctx := testutils.Context(t)
@@ -678,7 +677,7 @@ func Test_FetchBlocks(t *testing.T) {
func Test_PollAndSaveLogs_BackfillFinalityViolation(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
lpOpts := Opts{
PollPeriod: time.Second,
FinalityDepth: 3,
diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go
index 4b279760913..fe475135796 100644
--- a/core/chains/evm/logpoller/log_poller_test.go
+++ b/core/chains/evm/logpoller/log_poller_test.go
@@ -22,9 +22,8 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
-
"github.com/smartcontractkit/chainlink-common/pkg/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"
commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils"
@@ -33,12 +32,10 @@ import (
"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/shared/generated/log_emitter"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
- "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight"
"github.com/smartcontractkit/chainlink/v2/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/config/chaintype"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
@@ -90,7 +87,7 @@ func populateDatabase(t testing.TB, o logpoller.ORM, chainID *big.Int) (common.H
func BenchmarkSelectLogsCreatedAfter(b *testing.B) {
chainId := big.NewInt(137)
ctx := testutils.Context(b)
- _, db := heavyweight.FullTestDBV2(b, nil)
+ db := testutils.NewIndependentSqlxDB(b)
o := logpoller.NewORM(chainId, db, logger.Test(b))
event, address, _ := populateDatabase(b, o, chainId)
@@ -108,7 +105,7 @@ func BenchmarkSelectLogsCreatedAfter(b *testing.B) {
func TestPopulateLoadedDB(t *testing.T) {
t.Skip("Only for local load testing and query analysis")
- _, db := heavyweight.FullTestDBV2(t, nil)
+ db := testutils.NewIndependentSqlxDB(t)
ctx := testutils.Context(t)
chainID := big.NewInt(137)
@@ -687,7 +684,7 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) {
numChainInserts := 3
finalityDepth := 5
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
owner := testutils.MustNewSimTransactor(t)
owner.GasPrice = big.NewInt(10e9)
@@ -1463,7 +1460,7 @@ func TestLogPoller_DBErrorHandling(t *testing.T) {
lggr, observedLogs := logger.TestObserved(t, zapcore.WarnLevel)
chainID1 := testutils.NewRandomEVMChainID()
chainID2 := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
o := logpoller.NewORM(chainID1, db, lggr)
owner := testutils.MustNewSimTransactor(t)
@@ -1533,10 +1530,10 @@ func TestTooManyLogResults(t *testing.T) {
t.Parallel()
ctx := testutils.Context(t)
- ec := evmtest.NewEthClientMockWithDefaultChain(t)
+ ec := clienttest.NewClientWithDefaultChainID(t)
lggr, obs := logger.TestObserved(t, zapcore.DebugLevel)
chainID := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
o := logpoller.NewORM(chainID, db, lggr)
@@ -1961,10 +1958,10 @@ func Test_PruneOldBlocks(t *testing.T) {
func TestFindLCA(t *testing.T) {
ctx := testutils.Context(t)
- ec := evmtest.NewEthClientMockWithDefaultChain(t)
+ ec := clienttest.NewClientWithDefaultChainID(t)
lggr := logger.Test(t)
chainID := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := logpoller.NewORM(chainID, db, lggr)
diff --git a/core/chains/evm/logpoller/observability_test.go b/core/chains/evm/logpoller/observability_test.go
index 61760195700..c3cf912448c 100644
--- a/core/chains/evm/logpoller/observability_test.go
+++ b/core/chains/evm/logpoller/observability_test.go
@@ -15,8 +15,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
@@ -170,7 +169,7 @@ func generateRandomLogs(chainId, count int) []Log {
func createObservedORM(t *testing.T, chainId int64) *ObservedORM {
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
return NewObservedORM(big.NewInt(chainId), db, lggr)
}
diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go
index 620c4651874..2775e1d3478 100644
--- a/core/chains/evm/logpoller/orm_test.go
+++ b/core/chains/evm/logpoller/orm_test.go
@@ -23,9 +23,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
"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"
- "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
@@ -704,7 +702,7 @@ func TestLogPollerFilters(t *testing.T) {
lggr := logger.Test(t)
chainID := testutils.NewRandomEVMChainID()
- dbx := pgtest.NewSqlxDB(t)
+ dbx := testutils.NewSqlxDB(t)
orm := logpoller.NewORM(chainID, dbx, lggr)
event1 := EmitterABI.Events["Log1"].ID
@@ -1323,7 +1321,7 @@ func Test_ExecPagedQuery(t *testing.T) {
ctx := testutils.Context(t)
lggr := logger.Test(t)
chainID := testutils.NewRandomEVMChainID()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
o := logpoller.NewORM(chainID, db, lggr)
m := mockQueryExecutor{}
@@ -2045,9 +2043,9 @@ func TestInsertLogsWithBlock(t *testing.T) {
ctx := testutils.Context(t)
// We need full db here, because we want to test transaction rollbacks.
- // Using pgtest.NewSqlxDB(t) will run all tests in TXs which is not desired for this type of test
+ // Using testutils.NewSqlxDB(t) will run all tests in TXs which is not desired for this type of test
// (inner tx rollback will rollback outer tx, blocking rest of execution)
- _, db := heavyweight.FullTestDBV2(t, nil)
+ db := testutils.NewIndependentSqlxDB(t)
o := logpoller.NewORM(chainID, db, logger.Test(t))
correctLog := GenLog(chainID, 1, 1, utils.RandomAddress().String(), event[:], address)
@@ -2134,7 +2132,7 @@ func TestInsertLogsInTx(t *testing.T) {
ctx := testutils.Context(t)
// We need full db here, because we want to test transaction rollbacks.
- _, db := heavyweight.FullTestDBV2(t, nil)
+ db := testutils.NewIndependentSqlxDB(t)
o := logpoller.NewORM(chainID, db, logger.Test(t))
logs := make([]logpoller.Log, maxLogsSize, maxLogsSize+1)
@@ -2281,7 +2279,7 @@ func TestSelectLogsDataWordBetween(t *testing.T) {
func Benchmark_LogsDataWordBetween(b *testing.B) {
chainId := big.NewInt(137)
- _, db := heavyweight.FullTestDBV2(b, nil)
+ db := testutils.NewIndependentSqlxDB(b)
o := logpoller.NewORM(chainId, db, logger.Test(b))
ctx := testutils.Context(b)
@@ -2334,7 +2332,7 @@ func Benchmark_LogsDataWordBetween(b *testing.B) {
func Benchmark_DeleteExpiredLogs(b *testing.B) {
chainId := big.NewInt(137)
- _, db := heavyweight.FullTestDBV2(b, nil)
+ db := testutils.NewIndependentSqlxDB(b)
o := logpoller.NewORM(chainId, db, logger.Test(b))
ctx := testutils.Context(b)
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 1a2c445ef2d..9bdd9614cb5 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -35,16 +35,13 @@ import (
"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/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"
"github.com/smartcontractkit/chainlink/v2/evm/assets"
"github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
evmconfig "github.com/smartcontractkit/chainlink/v2/evm/config"
"github.com/smartcontractkit/chainlink/v2/evm/config/chaintype"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/evm/keystore"
@@ -53,14 +50,22 @@ import (
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
)
+var dbListenerCfg txmgr.ListenerConfig = testListenerConfig{}
+
+type testListenerConfig struct{}
+
+func (l testListenerConfig) FallbackPollInterval() time.Duration {
+ return 1 * time.Minute
+}
+
// NewEthBroadcaster creates a new txmgr.EthBroadcaster for use in testing.
func NewTestEthBroadcaster(
t testing.TB,
txStore txmgr.TestEvmTxStore,
ethClient client.Client,
keyStore keystore.Eth,
- gconfig chainlink.GeneralConfig,
- config evmconfig.ChainScopedConfig,
+ databaseListener txmgr.ListenerConfig,
+ config evmconfig.EVM,
checkerFactory txmgr.TransmitCheckerFactory,
nonceAutoSync bool,
nonceTracker txmgr.NonceTracker,
@@ -68,13 +73,19 @@ func NewTestEthBroadcaster(
t.Helper()
lggr := logger.Test(t)
- ge := config.EVM().GasEstimator()
+ ge := config.GasEstimator()
estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
- return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil)
+ return gas.NewFixedPriceEstimator(config.GasEstimator(), nil, ge.BlockHistory(), lggr, nil)
}, 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, "")
+ ethBroadcaster := txmgrcommon.NewBroadcaster(txStore,
+ txmgr.NewEvmTxmClient(ethClient, nil),
+ txmgr.NewEvmTxmConfig(config),
+ txmgr.NewEvmTxmFeeConfig(config.GasEstimator()),
+ config.Transactions(),
+ databaseListener, keyStore, txBuilder, nonceTracker,
+ lggr, checkerFactory, nonceAutoSync, "")
// Mark instance as test
ethBroadcaster.XXXTestDisableUnstartedTxAutoProcessing()
@@ -83,9 +94,9 @@ func NewTestEthBroadcaster(
}
func TestEthBroadcaster_Lifecycle(t *testing.T) {
- cfg, db := heavyweight.FullTestDBV2(t, nil)
+ db := testutils.NewIndependentSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -99,7 +110,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
txmgr.NewEvmTxmConfig(evmcfg.EVM()),
txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()),
evmcfg.EVM().Transactions(),
- cfg.Database().Listener(),
+ dbListenerCfg,
ethKeyStore,
txBuilder,
logger.Test(t),
@@ -141,10 +152,9 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) {
// Failure to load next sequnce map should not fail Broadcaster startup
func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -158,7 +168,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T)
txmgr.NewEvmTxmConfig(evmcfg.EVM()),
txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()),
evmcfg.EVM().Transactions(),
- cfg.Database().Listener(),
+ dbListenerCfg,
ethKeyStore,
txBuilder,
logger.Test(t),
@@ -174,8 +184,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T)
}
func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
ctx := tests.Context(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -183,14 +192,14 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
_, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
checkerFactory := &txmgr.CheckerFactory{Client: ethClient}
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
ethClient.On("NonceAt", mock.Anything, otherAddress, mock.Anything).Return(uint64(0), nil).Once()
lggr := logger.Test(t)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), checkerFactory, false, nonceTracker)
toAddress := gethCommon.HexToAddress("0x6C03DDA95a2AEd917EeCc6eddD4b9D16E6380411")
timeNow := time.Now()
@@ -381,16 +390,15 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
})
rnd := int64(1000000000 + rand.Intn(5000))
- cfg = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
- c.EVM[0].GasEstimator.TipCapDefault = assets.NewWeiI(rnd)
- c.EVM[0].GasEstimator.FeeCapDefault = assets.NewWeiI(rnd + 1)
- c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(rnd + 2)
+ evmcfg = configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EIP1559DynamicFees = ptr(true)
+ c.GasEstimator.TipCapDefault = assets.NewWeiI(rnd)
+ c.GasEstimator.FeeCapDefault = assets.NewWeiI(rnd + 1)
+ c.GasEstimator.PriceMax = assets.NewWeiI(rnd + 2)
})
- evmcfg = evmtest.NewChainScopedConfig(t, cfg)
ethClient.On("NonceAt", mock.Anything, otherAddress, mock.Anything).Return(uint64(1), nil).Once()
nonceTracker = txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb = NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker)
+ eb = NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), checkerFactory, false, nonceTracker)
t.Run("sends transactions with type 0x2 in EIP-1559 mode", func(t *testing.T) {
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
@@ -547,19 +555,18 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) {
}
func TestEthBroadcaster_TransmitChecking(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
ctx := tests.Context(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
checkerFactory := &testCheckerFactory{}
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), checkerFactory, false, nonceTracker)
checker := txmgr.TransmitCheckerSpec{
CheckerType: txmgr.TransmitCheckerTypeSimulate,
@@ -632,9 +639,9 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) {
func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testing.T) {
// non-transactional DB needed because we deliberately test for FK violation
- cfg, db := heavyweight.FullTestDBV2(t, nil)
+ db := testutils.NewIndependentSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- ccfg := evmtest.NewChainScopedConfig(t, cfg)
+ ccfg := configtest.NewChainScopedConfig(t, nil)
evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM())
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -657,7 +664,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi
evmcfg,
txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()),
ccfg.EVM().Transactions(),
- cfg.Database().Listener(),
+ dbListenerCfg,
ethKeyStore,
txBuilder,
logger.Test(t),
@@ -693,23 +700,22 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi
}
func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- // Configured gas price changed
- lm := decimal.RequireFromString("1.3")
- c.EVM[0].GasEstimator.LimitMultiplier = &lm
- })
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ // Configured gas price changed
+ lm := decimal.RequireFromString("1.3")
+ c.GasEstimator.LimitMultiplier = &lm
+ })
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
assert.Equal(t, int(1600), int(tx.Gas()))
@@ -742,12 +748,10 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
nextNonce := evmtypes.Nonce(916714082576372851)
firstNonce := nextNonce
secondNonce := nextNonce + 1
- cfg := configtest.NewGeneralConfig(t, nil)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ctx := tests.Context(t)
t.Run("cannot be more than one transaction per address in an unfinished state", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -782,16 +786,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
})
t.Run("previous run assigned nonce but never broadcast", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved
// the nonce to the eth_tx so evm.key_states.next_nonce has not been
@@ -821,16 +825,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
})
t.Run("previous run assigned nonce and broadcast but it fatally errored before we could save", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved the nonce to the eth_tx
inProgressEthTx := mustInsertInProgressEthTxWithAttempt(t, txStore, firstNonce, fromAddress)
@@ -858,16 +862,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
})
t.Run("previous run assigned nonce and broadcast and is now in mempool", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved the nonce to the eth_tx
inProgressEthTx := mustInsertInProgressEthTxWithAttempt(t, txStore, firstNonce, fromAddress)
@@ -894,16 +898,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
})
t.Run("previous run assigned nonce and broadcast and now the transaction has been confirmed", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved the nonce to the eth_tx
inProgressEthTx := mustInsertInProgressEthTxWithAttempt(t, txStore, firstNonce, fromAddress)
@@ -932,16 +936,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
t.Run("previous run assigned nonce and then failed to reach node for some reason and node is still down", func(t *testing.T) {
failedToReachNodeError := context.DeadlineExceeded
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved the nonce to the eth_tx
inProgressEthTx := mustInsertInProgressEthTxWithAttempt(t, txStore, firstNonce, fromAddress)
@@ -968,22 +972,21 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) {
})
t.Run("previous run assigned nonce and broadcast transaction then crashed and rebooted with a different configured gas price", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
// Configured gas price changed
- c.EVM[0].GasEstimator.PriceDefault = assets.NewWeiI(500000000000)
+ c.GasEstimator.PriceDefault = assets.NewWeiI(500000000000)
})
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Crashed right after we commit the database transaction that saved the nonce to the eth_tx
inProgressEthTx := mustInsertInProgressEthTxWithAttempt(t, txStore, firstNonce, fromAddress)
@@ -1036,20 +1039,18 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
gasLimit := uint64(242)
encodedPayload := []byte{0, 1}
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
lggr := logger.Test(t)
txmClient := txmgr.NewEvmTxmClient(ethClient, nil)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient)
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, configtest.NewChainScopedConfig(t, nil).EVM(), &testCheckerFactory{}, false, nonceTracker)
ctx := tests.Context(t)
require.NoError(t, commonutils.JustError(db.Exec(`SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`)))
@@ -1178,12 +1179,13 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// same as the parent test, but callback is set by ctor
t.Run("callback set by ctor", func(t *testing.T) {
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
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(), 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, "")
+ eb2 := txmgr.NewEvmBroadcaster(txStore, txmClient, txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), dbListenerCfg, ethKeyStore, txBuilder, lggr, &testCheckerFactory{}, false, "")
retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
assert.NoError(t, err)
assert.False(t, retryable)
@@ -1393,7 +1395,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
underpricedError := "transaction underpriced"
localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress)
etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID)
-
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
// First was underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg.EVM().GasEstimator().PriceDefault().ToInt()) == 0
@@ -1503,16 +1505,16 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// In this scenario the node operator REALLY fucked up and set the bump
// to zero (even though that should not be possible due to config
// validation)
- evmcfg2 := evmtest.NewChainScopedConfig(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.BumpMin = assets.NewWeiI(0)
- c.EVM[0].GasEstimator.BumpPercent = ptr[uint16](0)
- }))
- eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.BumpMin = assets.NewWeiI(0)
+ c.GasEstimator.BumpPercent = ptr[uint16](0)
+ })
+ eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID)
// First was underpriced
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
- return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg2.EVM().GasEstimator().PriceDefault().ToInt()) == 0
+ return tx.Nonce() == localNextNonce && tx.GasPrice().Cmp(evmcfg.EVM().GasEstimator().PriceDefault().ToInt()) == 0
}), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once()
// Do the thing
@@ -1522,7 +1524,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
assert.True(t, retryable)
// TEARDOWN: Clear out the unsent tx before the next test
- pgtest.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce)
})
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) {
@@ -1553,7 +1555,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
assert.Nil(t, attempt.BroadcastBeforeBlockNum)
})
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
t.Run("eth tx is left in progress if nonce is too high", func(t *testing.T) {
localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress)
@@ -1581,7 +1583,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
assert.Equal(t, txmgrtypes.TxAttemptInProgress, attempt.State)
assert.Nil(t, attempt.BroadcastBeforeBlockNum)
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
})
t.Run("eth node returns underpriced transaction and bumping gas doesn't increase it in EIP-1559 mode", func(t *testing.T) {
@@ -1592,14 +1594,14 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
// In this scenario the node operator REALLY fucked up and set the bump
// to zero (even though that should not be possible due to config
// validation)
- 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.BumpMin = assets.NewWeiI(0)
- c.EVM[0].GasEstimator.BumpPercent = ptr[uint16](0)
- }))
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EIP1559DynamicFees = ptr(true)
+ c.GasEstimator.BumpMin = assets.NewWeiI(0)
+ c.GasEstimator.BumpPercent = ptr[uint16](0)
+ })
localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(localNextNonce, nil).Once()
- eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker)
+ eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID)
underpricedError := "transaction underpriced"
localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress)
@@ -1613,7 +1615,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
require.Contains(t, err.Error(), "bumped gas tip cap of 1 wei is less than or equal to original gas tip cap of 1 wei")
assert.True(t, retryable)
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
})
t.Run("eth node returns underpriced transaction in EIP-1559 mode, bumps until inclusion", func(t *testing.T) {
@@ -1625,13 +1627,13 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
gasTipCapDefault := assets.NewWeiI(42)
- 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
- }))
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EIP1559DynamicFees = ptr(true)
+ c.GasEstimator.TipCapDefault = gasTipCapDefault
+ })
localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(localNextNonce, nil).Once()
- eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker)
+ eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
// Second was underpriced but above minimum
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
@@ -1639,11 +1641,11 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
}), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once()
// Resend at the bumped price
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
- return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), evmcfg2.EVM().GasEstimator().BumpMin().ToInt())) == 0
+ return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), evmcfg.EVM().GasEstimator().BumpMin().ToInt())) == 0
}), fromAddress).Return(multinode.Underpriced, errors.New(underpricedError)).Once()
// Final bump succeeds
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool {
- return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), big.NewInt(0).Mul(evmcfg2.EVM().GasEstimator().BumpMin().ToInt(), big.NewInt(2)))) == 0
+ return tx.Nonce() == localNextNonce && tx.GasTipCap().Cmp(big.NewInt(0).Add(gasTipCapDefault.ToInt(), big.NewInt(0).Mul(evmcfg.EVM().GasEstimator().BumpMin().ToInt(), big.NewInt(2)))) == 0
}), fromAddress).Return(multinode.Successful, nil).Once()
retryable, err := eb2.ProcessUnstartedTxs(ctx, fromAddress)
@@ -1651,7 +1653,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
assert.False(t, retryable)
// TEARDOWN: Clear out the unsent tx before the next test
- pgtest.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes WHERE nonce = $1`, localNextNonce)
})
}
@@ -1661,17 +1663,17 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T)
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
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
- config := evmtest.NewChainScopedConfig(t, cfg)
+ const limitMultiplier = float32(1.25)
+ config := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EstimateLimit = ptr(true) // Enabled gas limit estimation
+ c.GasEstimator.LimitMultiplier = ptr(decimal.NewFromFloat32(limitMultiplier)) // Set LimitMultiplier for the buffer
+ })
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
lggr := logger.Test(t)
@@ -1682,7 +1684,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T)
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, "")
+ eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), dbListenerCfg, ethKeyStore, txBuilder, nonceTracker, lggr, &testCheckerFactory{}, false, "")
// Mark instance as test
eb.XXXTestDisableUnstartedTxAutoProcessing()
@@ -1729,14 +1731,13 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) {
encodedPayload := []byte{0, 1}
localNonce := 0
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, nil)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
realKeystore := cltest.NewKeyStore(t, db)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, realKeystore.Eth())
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
kst := ksmocks.NewEth(t)
@@ -1745,7 +1746,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) {
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
lggr := logger.Test(t)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
ctx := tests.Context(t)
_, err := nonceTracker.GetNextSequence(ctx, fromAddress)
require.NoError(t, err)
@@ -1785,16 +1786,15 @@ func TestEthBroadcaster_Trigger(t *testing.T) {
t.Parallel()
// Simple sanity check to make sure it doesn't block
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, nil)
txStore := cltest.NewTestTxStore(t, db)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ethClient := clienttest.NewClientWithDefaultChainID(t)
lggr := logger.Test(t)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), &testCheckerFactory{}, false, nonceTracker)
eb.Trigger(testutils.NewAddress())
eb.Trigger(testutils.NewAddress())
@@ -1802,14 +1802,13 @@ func TestEthBroadcaster_Trigger(t *testing.T) {
}
func TestEthBroadcaster_SyncNonce(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ctx := tests.Context(t)
lggr, observed := logger.TestObserved(t, zapcore.DebugLevel)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].NonceAutoSync = ptr(true)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.NonceAutoSync = ptr(true)
})
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
evmTxmCfg := txmgr.NewEvmTxmConfig(evmcfg.EVM())
txStore := cltest.NewTestTxStore(t, db)
@@ -1832,7 +1831,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
kst.On("EnabledAddressesForChain", mock.Anything, testutils.FixtureChainID).Return(addresses, nil).Once()
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once()
txmClient := txmgr.NewEvmTxmClient(ethClient, nil)
- eb := txmgr.NewEvmBroadcaster(txStore, txmClient, evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, lggr, checkerFactory, false, "")
+ eb := txmgr.NewEvmBroadcaster(txStore, txmClient, evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), dbListenerCfg, kst, txBuilder, lggr, checkerFactory, false, "")
err := eb.Start(ctx)
assert.NoError(t, err)
@@ -1845,14 +1844,13 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
checkerFactory := &txmgr.CheckerFactory{Client: ethClient}
lggr := logger.Test(t)
ctx := tests.Context(t)
@@ -1866,7 +1864,7 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) {
// Tx with nonce 0 in DB will set local nonce map to value to 1
mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(inProgressTxNonce), fromAddress)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker)
+ eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, dbListenerCfg, evmcfg.EVM(), checkerFactory, false, nonceTracker)
// Check the local nonce map was set to 1 higher than in-progress tx nonce
nonce := getLocalNextNonce(t, nonceTracker, fromAddress)
@@ -1884,11 +1882,10 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) {
func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
lggr, observed := logger.TestObserved(t, zapcore.DebugLevel)
ge := evmcfg.EVM().GasEstimator()
@@ -1909,7 +1906,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) {
mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
+ eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), dbListenerCfg, ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
// Mark instance as test
eb.XXXTestDisableUnstartedTxAutoProcessing()
servicetest.Run(t, eb)
@@ -1930,7 +1927,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) {
mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
+ eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), dbListenerCfg, ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
// Mark instance as test
eb.XXXTestDisableUnstartedTxAutoProcessing()
servicetest.Run(t, eb)
@@ -1951,7 +1948,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) {
etx := mustInsertInProgressEthTxWithAttempt(t, txStore, evmtypes.Nonce(localNonce), fromAddress)
nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil))
- eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
+ eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), dbListenerCfg, ethKeyStore, txBuilder, nonceTracker, lggr, checkerFactory, false, string(chaintype.ChainHedera))
// Mark instance as test
eb.XXXTestDisableUnstartedTxAutoProcessing()
servicetest.Run(t, eb)
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index 1cf30743e1f..c1b19992a09 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -20,6 +20,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/services/servicetest"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink-framework/chains/fees"
txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr"
@@ -29,14 +30,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"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/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/evm/assets"
"github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
evmconfig "github.com/smartcontractkit/chainlink/v2/evm/config"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
"github.com/smartcontractkit/chainlink/v2/evm/gas"
gasmocks "github.com/smartcontractkit/chainlink/v2/evm/gas/mocks"
"github.com/smartcontractkit/chainlink/v2/evm/keystore"
@@ -46,11 +44,6 @@ import (
"github.com/smartcontractkit/chainlink/v2/evm/utils"
)
-func newTestChainScopedConfig(t *testing.T) (chainlink.GeneralConfig, evmconfig.ChainScopedConfig) {
- cfg := configtest.NewTestGeneralConfig(t)
- return cfg, evmtest.NewChainScopedConfig(t, cfg)
-}
-
func newBroadcastLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int64) txmgr.TxAttempt {
attempt := cltest.NewLegacyEthTxAttempt(t, etxID)
attempt.State = txmgrtypes.TxAttemptBroadcast
@@ -107,8 +100,8 @@ func mustInsertConfirmedEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce
func TestEthConfirmer_Lifecycle(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- gconfig, config := newTestChainScopedConfig(t)
+ db := testutils.NewSqlxDB(t)
+ config := configtest.NewChainScopedConfig(t, nil)
txStore := newTxStore(t, db)
ethClient := clienttest.NewClientWithDefaultChainID(t)
@@ -125,7 +118,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) {
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)
- ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht)
+ ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), confirmerConfig{}, ethKeyStore, txBuilder, lggr, stuckTxDetector, ht)
ctx := tests.Context(t)
// Can't close unstarted instance
@@ -187,13 +180,12 @@ func TestEthConfirmer_Lifecycle(t *testing.T) {
func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.GWei(500)
- })
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.GWei(500)
+ })
ctx := tests.Context(t)
blockNum := int64(100)
@@ -208,7 +200,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx1 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum)
etx2 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1))
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -228,7 +220,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
// Insert confirmed transaction that stays confirmed
etx := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -248,7 +240,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
// Insert terminally stuck transaction that stays fatal error
etx := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 0, blockNum)
mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx.TxAttempts[0].Hash)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -278,7 +270,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx4.TxAttempts[0].Hash)
// Insert unconfirmed transaction that is untouched
etx5 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1))
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(2), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -326,7 +318,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, blockNum, assets.NewWeiI(1))
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -341,7 +333,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 0, fromAddress)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -367,7 +359,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
etx4 := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 3, fromAddress)
// Insert unconfirmed transact that is not confirmed and left untouched
etx5 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1))
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(4), nil).Maybe()
require.NoError(t, ec.CheckForConfirmation(ctx, &head))
@@ -416,14 +408,13 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) {
func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewTestGeneralConfig(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, nil)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -444,7 +435,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) {
lggr := logger.Test(t)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
t.Run("returns nothing when there are no transactions", func(t *testing.T) {
etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID)
@@ -710,16 +701,15 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
t.Parallel()
lggr := logger.Test(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
t.Run("should retry previous attempt if connectivity check failed for legacy transactions", func(t *testing.T) {
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(false)
- c.EVM[0].GasEstimator.BlockHistory.BlockHistorySize = ptr[uint16](2)
- c.EVM[0].GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4)
+ ccfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EIP1559DynamicFees = ptr(false)
+ c.GasEstimator.BlockHistory.BlockHistorySize = ptr[uint16](2)
+ c.GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4)
})
- ccfg := evmtest.NewChainScopedConfig(t, cfg)
ctx := tests.Context(t)
txStore := cltest.NewTestTxStore(t, db)
@@ -738,7 +728,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), ccfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient)
ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0)
// Create confirmer with necessary state
- ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht)
+ ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), confirmerConfig{}, kst, txBuilder, lggr, stuckTxDetector, ht)
servicetest.Run(t, ec)
currentHead := int64(30)
oldEnough := int64(15)
@@ -763,12 +753,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
})
t.Run("should retry previous attempt if connectivity check failed for dynamic transactions", func(t *testing.T) {
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true)
- c.EVM[0].GasEstimator.BlockHistory.BlockHistorySize = ptr[uint16](2)
- c.EVM[0].GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4)
+ ccfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.EIP1559DynamicFees = ptr(true)
+ c.GasEstimator.BlockHistory.BlockHistorySize = ptr[uint16](2)
+ c.GasEstimator.BlockHistory.CheckInclusionBlocks = ptr[uint16](4)
})
- ccfg := evmtest.NewChainScopedConfig(t, cfg)
ctx := tests.Context(t)
txStore := cltest.NewTestTxStore(t, db)
@@ -787,7 +776,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe()
stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), ccfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient)
ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0)
- ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht)
+ ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), confirmerConfig{}, kst, txBuilder, lggr, stuckTxDetector, ht)
servicetest.Run(t, ec)
currentHead := int64(30)
oldEnough := int64(15)
@@ -815,17 +804,16 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.GWei(500)
- })
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.GWei(500)
+ })
_, _ = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -834,7 +822,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) {
addresses := []gethCommon.Address{fromAddress}
kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe()
// Use a mock keystore for this test
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil)
currentHead := int64(30)
oldEnough := int64(19)
nonce := int64(0)
@@ -883,27 +871,26 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) {
func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
t.Parallel()
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.GWei(500)
- c.EVM[0].GasEstimator.BumpMin = assets.NewWeiI(0)
- })
ctx := tests.Context(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.GWei(500)
+ c.GasEstimator.BumpMin = assets.NewWeiI(0)
+ })
currentHead := int64(30)
t.Run("does nothing if no transactions require bumping", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead))
})
t.Run("re-sends previous transaction on keystore error", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -918,7 +905,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
}),
mock.Anything).Return(nil, errors.New("signing error")).Once()
// Use a mock keystore for this test
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil)
err := ec.RebroadcastWhereNecessary(ctx, currentHead)
require.Error(t, err)
@@ -932,12 +919,12 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("does nothing and continues on fatal error", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, assets.NewWeiI(100))
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -951,13 +938,13 @@ 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) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
latestGasPrice := assets.GWei(20)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -978,12 +965,12 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("does nothing if there is an attempt without BroadcastBeforeBlockNum set", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 0, fromAddress, txmgrtypes.TxAttemptBroadcast)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead))
var err error
@@ -994,13 +981,13 @@ 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) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
latestGasPrice := assets.GWei(20)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1021,13 +1008,13 @@ 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) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
latestGasPrice := assets.GWei(20)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1051,14 +1038,14 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("saves in-progress attempt on temporary error and returns error", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
latestGasPrice := assets.GWei(20)
broadcastBlockNum := int64(25)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, latestGasPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1102,14 +1089,14 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
latestGasPrice := assets.GWei(20)
broadcastBlockNum := int64(25)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, latestGasPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1133,19 +1120,18 @@ 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) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
priceMax := assets.GWei(30)
- gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = priceMax
+ newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = priceMax
})
- newCfg := evmtest.NewChainScopedConfig(t, gcfg)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
broadcastBlockNum := int64(25)
currentAttemptPrice := priceMax.Sub(assets.GWei(1))
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, currentAttemptPrice)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, newCfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1165,18 +1151,17 @@ 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) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
priceMax := assets.GWei(30)
- gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = priceMax
+ newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = priceMax
})
- newCfg := evmtest.NewChainScopedConfig(t, gcfg)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
broadcastBlockNum := int64(25)
etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, priceMax)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, newCfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1196,18 +1181,17 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("EIP-1559: bumps using EIP-1559 rules when existing attempts are of type 0x2", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.BumpMin = assets.GWei(1)
+ newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.BumpMin = assets.GWei(1)
})
- newCfg := evmtest.NewChainScopedConfig(t, gcfg)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress)
err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25))
require.NoError(t, err)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, newCfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1228,18 +1212,17 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("EIP-1559: resubmits at the old price and does not create a new attempt if one of the bumped EIP-1559 transactions would have its tip cap exceed EVM.GasEstimator.PriceMax", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(1)
+ newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.NewWeiI(1)
})
- newCfg := evmtest.NewChainScopedConfig(t, gcfg)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress)
err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25))
require.NoError(t, err)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, newCfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1258,19 +1241,18 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
})
t.Run("EIP-1559: re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
- gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.BumpMin = assets.GWei(1)
+ newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.BumpMin = assets.GWei(1)
})
- newCfg := evmtest.NewChainScopedConfig(t, gcfg)
// 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)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress)
err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25))
require.NoError(t, err)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, newCfg, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115
@@ -1296,15 +1278,14 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) {
func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesThrough(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.GWei(500)
- })
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.GWei(500)
+ })
_, _ = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1319,7 +1300,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
t.Run("terminally underpriced transaction with in_progress attempt is retried with more gas", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil)
originalBroadcastAt := time.Unix(1616509100, 0)
etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, nonce, fromAddress, txmgrtypes.TxAttemptInProgress, originalBroadcastAt)
@@ -1343,7 +1324,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
t.Run("multiple gas bumps with existing broadcast attempts are retried with more gas until success in legacy mode", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil)
etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress)
nonce++
@@ -1375,7 +1356,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
t.Run("multiple gas bumps with existing broadcast attempts are retried with more gas until success in EIP-1559 mode", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil)
etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, nonce, fromAddress)
nonce++
@@ -1408,7 +1389,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh
func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
@@ -1423,7 +1404,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
// keyStates, err := ethKeyStore.GetStatesForKeys(keys)
// require.NoError(t, err)
- gconfig, config := newTestChainScopedConfig(t)
+ config := configtest.NewChainScopedConfig(t, nil)
currentHead := int64(30)
oldEnough := int64(19)
nonce := int64(0)
@@ -1439,7 +1420,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
insufficientEthError := errors.New("insufficient funds for gas * price + value")
t.Run("saves attempt with state 'insufficient_eth' if eth node returns this error", func(t *testing.T) {
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
expectedBumpedGasPrice := big.NewInt(20000000000)
require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64())
@@ -1465,7 +1446,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
})
t.Run("does not bump gas when previous error was 'out of eth', instead resubmits existing transaction", func(t *testing.T) {
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
expectedBumpedGasPrice := big.NewInt(20000000000)
require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64())
@@ -1490,7 +1471,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
})
t.Run("saves the attempt as broadcast after node wallet has been topped up with sufficient balance", func(t *testing.T) {
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
expectedBumpedGasPrice := big.NewInt(20000000000)
require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64())
@@ -1518,11 +1499,10 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
depth := 2
etxCount := 4
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.BumpTxDepth = ptr(uint32(depth))
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.BumpTxDepth = ptr(uint32(depth))
})
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
for i := 0; i < etxCount; i++ {
n := nonce
@@ -1546,10 +1526,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) {
func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.PriceMax = assets.GWei(500)
- })
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
@@ -1557,10 +1534,12 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing.
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.PriceMax = assets.GWei(500)
+ })
// Use a mock keystore for this test
- ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil)
currentHead := int64(30)
oldEnough := int64(19)
nonce := int64(0)
@@ -1598,13 +1577,13 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing.
func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
- gconfig, config := newTestChainScopedConfig(t)
+ config := configtest.NewChainScopedConfig(t, nil)
mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, config.EVM().ChainID())
mustInsertInProgressEthTx(t, txStore, 0, fromAddress)
etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress)
@@ -1615,7 +1594,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Run("rebroadcasts one eth_tx if it falls within in nonce range", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx1.Sequence) &&
@@ -1630,7 +1609,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Run("uses default gas limit if overrideGasLimit is 0", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(*etx1.Sequence) &&
@@ -1645,7 +1624,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Run("rebroadcasts several eth_txes in nonce range", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, 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.GasPrice.Int64() && tx.Gas() == overrideGasLimit
@@ -1659,7 +1638,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Run("broadcasts zero transactions if eth_tx doesn't exist for that nonce", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(1)
@@ -1685,7 +1664,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
t.Run("zero transactions use default gas limit if override wasn't specified", func(t *testing.T) {
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil)
+ ec := newEthConfirmer(t, txStore, ethClient, config, ethKeyStore, nil)
ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool {
return tx.Nonce() == uint64(0) && tx.GasPrice().Int64() == gasPriceWei.GasPrice.Int64() && tx.Gas() == config.EVM().GasEstimator().LimitDefault()
@@ -1698,7 +1677,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) {
func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
@@ -1717,18 +1696,17 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) {
autoPurgeThreshold := uint32(5)
autoPurgeMinAttempts := uint32(3)
limitDefault := uint64(100)
- cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].GasEstimator.LimitDefault = ptr(limitDefault)
- c.EVM[0].Transactions.AutoPurge.Enabled = ptr(true)
- c.EVM[0].Transactions.AutoPurge.Threshold = ptr(autoPurgeThreshold)
- c.EVM[0].Transactions.AutoPurge.MinAttempts = ptr(autoPurgeMinAttempts)
+ evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.GasEstimator.LimitDefault = ptr(limitDefault)
+ c.Transactions.AutoPurge.Enabled = ptr(true)
+ c.Transactions.AutoPurge.Threshold = ptr(autoPurgeThreshold)
+ c.Transactions.AutoPurge.MinAttempts = ptr(autoPurgeMinAttempts)
})
- evmcfg := evmtest.NewChainScopedConfig(t, cfg)
ge := evmcfg.EVM().GasEstimator()
txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator)
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.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht)
+ ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), confirmerConfig{}, 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
@@ -1746,7 +1724,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) {
// 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)
+ testutils.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,
@@ -1796,7 +1774,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) {
func ptr[T any](t T) *T { return &t }
-func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Client, gconfig chainlink.GeneralConfig, config evmconfig.ChainScopedConfig, ks keystore.Eth, fn txmgrcommon.ResumeCallback) *txmgr.Confirmer {
+func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Client, config evmconfig.ChainScopedConfig, ks keystore.Eth, fn txmgrcommon.ResumeCallback) *txmgr.Confirmer {
lggr := logger.Test(t)
ge := config.EVM().GasEstimator()
estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
@@ -1805,8 +1783,16 @@ func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Cl
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)
- ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ks, txBuilder, lggr, stuckTxDetector, ht)
+ ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), confirmerConfig{}, ks, txBuilder, lggr, stuckTxDetector, ht)
ec.SetResumeCallback(fn)
servicetest.Run(t, ec)
return ec
}
+
+var _ txmgrtypes.ConfirmerDatabaseConfig = confirmerConfig{}
+
+type confirmerConfig struct{}
+
+func (d confirmerConfig) DefaultQueryTimeout() time.Duration {
+ return 10 * time.Second
+}
diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go
index b5ea7b9d0d6..e23da197fda 100644
--- a/core/chains/evm/txmgr/evm_tx_store_test.go
+++ b/core/chains/evm/txmgr/evm_tx_store_test.go
@@ -23,13 +23,11 @@ import (
"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/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/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/evm/assets"
"github.com/smartcontractkit/chainlink/v2/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/gas"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/types"
@@ -37,7 +35,7 @@ import (
)
func TestORM_TransactionsWithAttempts(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -82,7 +80,7 @@ func TestORM_TransactionsWithAttempts(t *testing.T) {
}
func TestORM_Transactions(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -121,7 +119,7 @@ func TestORM_Transactions(t *testing.T) {
func TestORM(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db)
orm := cltest.NewTestTxStore(t, db)
_, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth())
@@ -188,7 +186,7 @@ func TestORM(t *testing.T) {
}
func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
orm := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -238,7 +236,7 @@ func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) {
func TestORM_FindTxAttemptsRequiringResend(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
@@ -325,7 +323,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) {
func TestORM_UpdateBroadcastAts(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db)
orm := cltest.NewTestTxStore(t, db)
_, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth())
@@ -373,11 +371,11 @@ func TestORM_UpdateBroadcastAts(t *testing.T) {
func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- _, cfg := newTestChainScopedConfig(t)
+ db := testutils.NewSqlxDB(t)
+ cfg := configtest.NewChainScopedConfig(t, nil)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress)
chainID := ethClient.ConfiguredChainID()
@@ -443,7 +441,7 @@ func TestORM_UpdateTxConfirmed(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -470,7 +468,7 @@ func TestORM_UpdateTxConfirmed(t *testing.T) {
func TestORM_SaveFetchedReceipts(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -517,7 +515,7 @@ func TestORM_SaveFetchedReceipts(t *testing.T) {
func TestORM_PreloadTxes(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -550,10 +548,10 @@ func TestORM_PreloadTxes(t *testing.T) {
func TestORM_GetInProgressTxAttempts(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
// insert etx with attempt
@@ -570,14 +568,14 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) {
func TestORM_FindTxesPendingCallback(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
- 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`)
+ testutils.MustExec(t, db, `SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`)
+ testutils.MustExec(t, db, `SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`)
h8 := &types.Head{
Number: 8,
@@ -598,41 +596,41 @@ func TestORM_FindTxesPendingCallback(t *testing.T) {
// Suspended run waiting for callback
run1 := cltest.MustInsertPipelineRun(t, db)
tr1 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run1.ID)
- pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run1.ID)
+ testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run1.ID)
etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
attempt1 := etx1.TxAttempts[0]
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)
+ testutils.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
- run2 := cltest.MustInsertPipelineRunWithStatus(t, db, 0, pipeline.RunStatusCompleted, 0)
+ run2 := cltest.MustInsertPipelineRunWithStatus(t, db, 0, "completed", 0)
tr2 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run2.ID)
etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
attempt2 := etx2.TxAttempts[0]
mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt2.Hash)
- 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`, &tr2.ID, minConfirmations, etx2.ID)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr2.ID, minConfirmations, etx2.ID)
// Suspended run younger than minConfirmations. Should be ignored
run3 := cltest.MustInsertPipelineRun(t, db)
tr3 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run3.ID)
- pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run3.ID)
+ testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run3.ID)
etx3 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 5, 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`)
attempt3 := etx3.TxAttempts[0]
mustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt3.Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr3.ID, minConfirmations, etx3.ID)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr3.ID, minConfirmations, etx3.ID)
// Tx not marked for callback. Should be ignore
etx4 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress)
attempt4 := etx4.TxAttempts[0]
mustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt4.Hash)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx4.ID)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx4.ID)
// Unconfirmed Tx without receipts. Should be ignored
etx5 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx5.ID)
+ testutils.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, 0, ethClient.ConfiguredChainID())
@@ -642,7 +640,7 @@ func TestORM_FindTxesPendingCallback(t *testing.T) {
}
// Clear min_confirmations
- pgtest.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = NULL WHERE id = $1`, etx1.ID)
+ testutils.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())
@@ -659,8 +657,8 @@ func TestORM_FindTxesPendingCallback(t *testing.T) {
func Test_FindTxWithIdempotencyKey(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- _, cfg := newTestChainScopedConfig(t)
+ db := testutils.NewSqlxDB(t)
+ cfg := configtest.NewChainScopedConfig(t, nil)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -689,7 +687,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) {
func TestORM_FindTxWithSequence(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -713,7 +711,7 @@ func TestORM_FindTxWithSequence(t *testing.T) {
func TestORM_UpdateTxForRebroadcast(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -785,10 +783,10 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) {
func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
t.Run("no unconfirmed eth txes", func(t *testing.T) {
@@ -808,10 +806,10 @@ func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) {
func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
_, fromAddress2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -839,7 +837,7 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -863,7 +861,7 @@ func TestORM_SaveSentAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -888,7 +886,7 @@ func TestORM_SaveConfirmedAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -913,7 +911,7 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -935,7 +933,7 @@ func TestORM_SaveInProgressAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -975,10 +973,10 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
currentBlockNum := int64(10)
@@ -1014,7 +1012,7 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) {
func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
@@ -1059,8 +1057,8 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin
})
t.Run("does not return confirmed or fatally errored eth_txes", func(t *testing.T) {
- pgtest.MustExec(t, db, `UPDATE evm.txes SET state='confirmed' WHERE id = $1`, etx1.ID)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET state='fatal_error', nonce=NULL, error='foo', broadcast_at=NULL, initial_broadcast_at=NULL WHERE id = $1`, etx2.ID)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET state='confirmed' WHERE id = $1`, etx1.ID)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET state='fatal_error', nonce=NULL, error='foo', broadcast_at=NULL, initial_broadcast_at=NULL WHERE id = $1`, etx2.ID)
etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(tests.Context(t), fromAddress, testutils.FixtureChainID)
require.NoError(t, err)
@@ -1076,7 +1074,7 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1129,7 +1127,7 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1152,10 +1150,10 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) {
func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1179,7 +1177,7 @@ func TestORM_UpdateTxFatalErrorAndDeleteAttempts(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1203,7 +1201,7 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1234,7 +1232,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1267,7 +1265,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) {
require.ErrorContains(t, err, "tx removed")
})
- db = pgtest.NewSqlxDB(t)
+ db = testutils.NewSqlxDB(t)
txStore = cltest.NewTestTxStore(t, db)
ethKeyStore = cltest.NewKeyStore(t, db).Eth()
_, fromAddress = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1277,15 +1275,13 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) {
require.Len(t, etx.TxAttempts, 1)
zero := commonconfig.MustNewDuration(time.Duration(0))
- evmCfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
- c.EVM[0].Chain.Transactions.ReaperInterval = zero
- c.EVM[0].Chain.Transactions.ReaperThreshold = zero
- c.EVM[0].Chain.Transactions.ResendAfterThreshold = zero
+ ccfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) {
+ c.Transactions.ReaperInterval = zero
+ c.Transactions.ReaperThreshold = zero
+ c.Transactions.ResendAfterThreshold = zero
})
-
- ccfg := evmtest.NewChainScopedConfig(t, evmCfg)
evmTxmCfg := txmgr.NewEvmTxmConfig(ccfg.EVM())
- ec := evmtest.NewEthClientMockWithDefaultChain(t)
+ ec := clienttest.NewClientWithDefaultChainID(t)
txMgr := txmgr.NewEvmTxm(ec.ConfiguredChainID(), evmTxmCfg, ccfg.EVM().Transactions(), nil, logger.Test(t), nil, nil,
nil, txStore, nil, nil, nil, nil, nil, nil)
err := txMgr.XXXTestAbandon(fromAddress) // mark transaction as abandoned
@@ -1321,7 +1317,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) {
func TestORM_GetTxInProgress(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1344,10 +1340,10 @@ func TestORM_GetTxInProgress(t *testing.T) {
func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
_, enabled := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
enabledAddrs := []common.Address{enabled}
@@ -1401,7 +1397,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) {
func TestORM_GetTxByID(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1423,7 +1419,7 @@ func TestORM_GetTxByID(t *testing.T) {
func TestORM_GetFatalTransactions(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1445,10 +1441,10 @@ func TestORM_GetFatalTransactions(t *testing.T) {
func TestORM_HasInProgressTransaction(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
t.Run("no in progress eth transaction", func(t *testing.T) {
@@ -1469,7 +1465,7 @@ func TestORM_HasInProgressTransaction(t *testing.T) {
func TestORM_CountUnconfirmedTransactions(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1489,7 +1485,7 @@ func TestORM_CountUnconfirmedTransactions(t *testing.T) {
func TestORM_CountTransactionsByState(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1509,7 +1505,7 @@ func TestORM_CountTransactionsByState(t *testing.T) {
func TestORM_CountUnstartedTransactions(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1529,7 +1525,7 @@ func TestORM_CountUnstartedTransactions(t *testing.T) {
func TestORM_CheckTxQueueCapacity(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1624,7 +1620,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) {
func TestORM_CreateTransaction(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := newTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
@@ -1633,7 +1629,7 @@ func TestORM_CreateTransaction(t *testing.T) {
gasLimit := uint64(1000)
payload := []byte{1, 2, 3}
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
t.Run("with queue under capacity inserts eth_tx", func(t *testing.T) {
subject := uuid.New()
@@ -1723,10 +1719,10 @@ func TestORM_CreateTransaction(t *testing.T) {
func TestORM_PruneUnstartedTxQueue(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := txmgr.NewTxStore(db, logger.Test(t))
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
- evmtest.NewEthClientMockWithDefaultChain(t)
+
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
t.Run("does not prune if queue has not exceeded capacity-1", func(t *testing.T) {
@@ -1751,7 +1747,7 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) {
func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -1784,7 +1780,7 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) {
blockNum := int64(100)
t.Run("finds confirmed transaction requiring receipt fetch", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
_, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth())
@@ -1816,7 +1812,7 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) {
})
t.Run("finds terminally stuck transaction requiring receipt fetch", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
_, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth())
@@ -1849,7 +1845,7 @@ func TestORM_UpdateTxStatesToFinalizedUsingTxHashes(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
broadcast := time.Now()
@@ -1883,7 +1879,7 @@ func TestORM_FindReorgOrIncludedTxs(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
blockNum := int64(100)
@@ -1946,7 +1942,7 @@ func TestORM_UpdateTxFatalError(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
_, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth())
@@ -1972,7 +1968,7 @@ func TestORM_UpdateTxFatalError(t *testing.T) {
func TestORM_FindTxesByIDs(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -1996,7 +1992,7 @@ func TestORM_FindTxesByIDs(t *testing.T) {
func TestORM_DeleteReceiptsByTxHash(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -2023,7 +2019,7 @@ func TestORM_DeleteReceiptsByTxHash(t *testing.T) {
func TestORM_Abandon(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ctx := tests.Context(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
diff --git a/core/chains/evm/txmgr/finalizer_test.go b/core/chains/evm/txmgr/finalizer_test.go
index 1573414e0df..7fef240370d 100644
--- a/core/chains/evm/txmgr/finalizer_test.go
+++ b/core/chains/evm/txmgr/finalizer_test.go
@@ -27,11 +27,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker"
"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/configtest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/types"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
@@ -40,7 +38,7 @@ import (
func TestFinalizer_MarkTxFinalized(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
feeLimit := uint64(10_000)
@@ -255,7 +253,7 @@ func insertTxAndAttemptWithIdempotencyKey(t *testing.T, txStore txmgr.TestEvmTxS
func TestFinalizer_ResumePendingRuns(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ethClient := clienttest.NewClientWithDefaultChainID(t)
@@ -280,8 +278,8 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
minConfirmations := int64(2)
- 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`)
+ testutils.MustExec(t, db, `SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`)
+ testutils.MustExec(t, db, `SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`)
t.Run("doesn't process task runs that are not suspended (possibly already previously resumed)", func(t *testing.T) {
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -299,7 +297,7 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash)
// Setting both signal_callback and callback_completed to TRUE to simulate a completed pipeline task
// 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)
+ testutils.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 := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0)
require.NoError(t, err)
@@ -320,7 +318,7 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress)
mustInsertEthReceipt(t, txStore, head.Number, 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)
+ testutils.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 := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0)
require.NoError(t, err)
@@ -341,13 +339,13 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
run := cltest.MustInsertPipelineRun(t, db)
tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
- pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
+ testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
receipt := 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)
+ testutils.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)
done := make(chan struct{})
t.Cleanup(func() { <-done })
@@ -375,7 +373,7 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
}
})
- pgtest.MustExec(t, db, `DELETE FROM pipeline_runs`)
+ testutils.MustExec(t, db, `DELETE FROM pipeline_runs`)
t.Run("processes transactions with receipt older than minConfirmations that reverted", func(t *testing.T) {
type data struct {
@@ -394,15 +392,15 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
run := cltest.MustInsertPipelineRun(t, db)
tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID)
- pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
+ testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID)
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`)
// receipt is not passed through as a value since it reverted and caused an error
mustInsertRevertedEthReceipt(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)
+ testutils.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)
done := make(chan struct{})
t.Cleanup(func() { <-done })
@@ -444,7 +442,7 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress)
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)
+ testutils.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 := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0)
require.Error(t, err)
@@ -459,8 +457,8 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) {
func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- cfg := configtest.NewTestGeneralConfig(t)
- config := evmtest.NewChainScopedConfig(t, cfg)
+
+ config := configtest.NewChainScopedConfig(t, nil)
ethClient := clienttest.NewClientWithDefaultChainID(t)
txmClient := txmgr.NewEvmTxmClient(ethClient, nil)
rpcBatchSize := config.EVM().RPCDefaultBatchSize()
@@ -478,7 +476,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
head.Parent.Store(latestFinalizedHead)
t.Run("does nothing if no confirmed transactions without receipts found", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -497,7 +495,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("fetches receipt for confirmed transaction without a receipt", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -524,7 +522,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("saves nothing if returned receipt does not match the attempt", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -557,7 +555,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("saves nothing if query returns error", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -591,7 +589,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("saves valid receipt returned by client", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -646,7 +644,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("fetches and saves receipts for several attempts in gas price order", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -699,7 +697,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("ignores receipt missing BlockHash that comes from querying parity too early", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -731,7 +729,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("does not panic if receipt has BlockHash but is missing some other fields somehow", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -764,7 +762,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("simulate on revert", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -811,7 +809,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("find receipt for old transaction, avoid marking as fatal", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -846,7 +844,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) {
})
t.Run("old transaction failed to find receipt, marked as fatal", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -893,7 +891,7 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) {
head.Parent.Store(latestFinalizedHead)
t.Run("fetch and store receipts from multiple batch calls", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -942,7 +940,7 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) {
})
t.Run("continue to fetch and store receipts after batch call error", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1004,7 +1002,7 @@ func TestFinalizer_FetchAndStoreReceipts_HandlesNonFwdTxsWithForwardingEnabled(t
}
head.Parent.Store(latestFinalizedHead)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1062,14 +1060,14 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) {
head.Parent.Store(latestFinalizedHead)
t.Run("does nothing if no old transactions found", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht)
require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, []int64{}, head, latestFinalizedHead))
})
t.Run("marks multiple old transactions as fatal", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1096,7 +1094,7 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) {
})
t.Run("marks old transaction as fatal, resumes pending task as failed", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
@@ -1131,7 +1129,7 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) {
})
t.Run("transaction stays confirmed if failure to resume pending task", func(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore)
diff --git a/core/chains/evm/txmgr/models.go b/core/chains/evm/txmgr/models.go
index bf5e7251744..1ebbe54c887 100644
--- a/core/chains/evm/txmgr/models.go
+++ b/core/chains/evm/txmgr/models.go
@@ -24,7 +24,7 @@ type (
Reaper = txmgr.Reaper[*big.Int]
TxStore = txmgrtypes.TxStore[common.Address, *big.Int, common.Hash, common.Hash, *evmtypes.Receipt, evmtypes.Nonce, gas.EvmFee]
TransactionStore = txmgrtypes.TransactionStore[common.Address, *big.Int, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
- KeyStore = txmgrtypes.KeyStore[common.Address, *big.Int, evmtypes.Nonce]
+ KeyStore = txmgrtypes.KeyStore[common.Address, *big.Int]
TxAttemptBuilder = txmgrtypes.TxAttemptBuilder[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
NonceTracker = txmgrtypes.SequenceTracker[common.Address, evmtypes.Nonce]
TransmitCheckerFactory = txmgr.TransmitCheckerFactory[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]
diff --git a/core/chains/evm/txmgr/nonce_tracker_test.go b/core/chains/evm/txmgr/nonce_tracker_test.go
index fc0cf86bd2b..8bcadcc656c 100644
--- a/core/chains/evm/txmgr/nonce_tracker_test.go
+++ b/core/chains/evm/txmgr/nonce_tracker_test.go
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math/big"
+ "math/rand"
"testing"
"github.com/stretchr/testify/mock"
@@ -17,9 +18,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
txstoremock "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
"github.com/smartcontractkit/chainlink/v2/evm/types"
)
@@ -40,8 +40,8 @@ func TestNonceTracker_LoadSequenceMap(t *testing.T) {
enabledAddresses := []common.Address{addr1, addr2}
t.Run("set next nonce using entries from tx table", func(t *testing.T) {
- randNonce1 := testutils.NewRandomPositiveInt64()
- randNonce2 := testutils.NewRandomPositiveInt64()
+ randNonce1 := rand.Int63()
+ randNonce2 := rand.Int63()
txStore.On("FindLatestSequence", mock.Anything, addr1, chainID).Return(types.Nonce(randNonce1), nil).Once()
txStore.On("FindLatestSequence", mock.Anything, addr2, chainID).Return(types.Nonce(randNonce2), nil).Once()
@@ -59,8 +59,8 @@ func TestNonceTracker_LoadSequenceMap(t *testing.T) {
txStore.On("FindLatestSequence", mock.Anything, addr1, chainID).Return(emptyNonce, errors.New("no rows")).Once()
txStore.On("FindLatestSequence", mock.Anything, addr2, chainID).Return(emptyNonce, errors.New("no rows")).Once()
- randNonce1 := testutils.NewRandomPositiveInt64()
- randNonce2 := testutils.NewRandomPositiveInt64()
+ randNonce1 := rand.Int63()
+ randNonce2 := rand.Int63()
client.On("NonceAt", mock.Anything, addr1, mock.Anything).Return(uint64(randNonce1), nil).Once() //nolint:gosec // Disable G115: randNonce1 always positive
client.On("NonceAt", mock.Anything, addr2, mock.Anything).Return(uint64(randNonce2), nil).Once() //nolint:gosec // Disable G115: randNonce2 always positive
@@ -242,7 +242,7 @@ func TestNonceTracker_GenerateNextSequence(t *testing.T) {
addr := common.HexToAddress("0xd5e099c71b797516c10ed0f0d895f429c2781142")
enabledAddresses := []common.Address{addr}
- randNonce := testutils.NewRandomPositiveInt64()
+ randNonce := rand.Int63()
txStore.On("FindLatestSequence", mock.Anything, addr, chainID).Return(types.Nonce(randNonce), nil).Once()
nonceTracker.LoadNextSequences(ctx, enabledAddresses)
seq, err := nonceTracker.GetNextSequence(ctx, addr)
@@ -261,7 +261,7 @@ func Test_SetNonceAfterInit(t *testing.T) {
ctx := tests.Context(t)
chainID := big.NewInt(0)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := txmgr.NewTxStore(db, logger.Test(t))
client := clienttest.NewClient(t)
@@ -271,7 +271,7 @@ func Test_SetNonceAfterInit(t *testing.T) {
addr := common.HexToAddress("0xd5e099c71b797516c10ed0f0d895f429c2781142")
enabledAddresses := []common.Address{addr}
- randNonce := testutils.NewRandomPositiveInt64()
+ randNonce := rand.Int63()
client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(0), errors.New("failed to retrieve nonce at startup")).Once()
client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(randNonce), nil).Once() //nolint:gosec // Disable G115: randNonce always positive
nonceTracker.LoadNextSequences(ctx, enabledAddresses)
diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go
index a60da02371d..3c5f6a06a98 100644
--- a/core/chains/evm/txmgr/reaper_test.go
+++ b/core/chains/evm/txmgr/reaper_test.go
@@ -14,7 +14,7 @@ import (
txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types"
"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/pgtest"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
)
func newReaperWithChainID(t *testing.T, db txmgrtypes.TxHistoryReaper[*big.Int], txConfig txmgrtypes.ReaperTransactionsConfig, cid *big.Int) *txmgr.Reaper {
@@ -41,7 +41,7 @@ func (r *reaperConfig) ReaperThreshold() time.Duration {
func TestReaper_ReapTxes(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -93,7 +93,7 @@ func TestReaper_ReapTxes(t *testing.T) {
// Didn't delete because eth_tx was not old enough
cltest.AssertCount(t, db, "evm.txes", 1)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET created_at=$1, state='finalized'`, oneDayAgo)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET created_at=$1, state='finalized'`, oneDayAgo)
err = r.ReapTxes(42)
assert.NoError(t, err)
@@ -133,7 +133,7 @@ func TestReaper_ReapTxes(t *testing.T) {
// Didn't delete because eth_tx was not old enough
cltest.AssertCount(t, db, "evm.txes", 1)
- pgtest.MustExec(t, db, `UPDATE evm.txes SET created_at=$1`, oneDayAgo)
+ testutils.MustExec(t, db, `UPDATE evm.txes SET created_at=$1`, oneDayAgo)
err = r.ReapTxes(42)
assert.NoError(t, err)
diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go
index d16073fda0c..f44b51bb2f3 100644
--- a/core/chains/evm/txmgr/resender_test.go
+++ b/core/chains/evm/txmgr/resender_test.go
@@ -19,7 +19,6 @@ import (
"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/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/testutils"
@@ -29,7 +28,7 @@ import (
func Test_EthResender_resendUnconfirmed(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
lggr := logger.Test(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ethClient := clienttest.NewClientWithDefaultChainID(t)
@@ -99,7 +98,7 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) {
func Test_EthResender_alertUnconfirmed(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
lggr, o := logger.TestObserved(t, zapcore.DebugLevel)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ethClient := clienttest.NewClientWithDefaultChainID(t)
@@ -137,7 +136,7 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) {
func Test_EthResender_Start(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ccfg := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) {
// This can be anything as long as it isn't zero
c.Transactions.ResendAfterThreshold = commonconfig.MustNewDuration(42 * time.Hour)
diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go
index 4c366c6f242..7c3eb302311 100644
--- a/core/chains/evm/txmgr/stuck_tx_detector_test.go
+++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go
@@ -17,13 +17,13 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/configtest"
txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types"
"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/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/assets"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/config/chaintype"
@@ -41,7 +41,7 @@ var (
func TestStuckTxDetector_Disabled(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
_, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore)
@@ -64,7 +64,7 @@ func TestStuckTxDetector_Disabled(t *testing.T) {
func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -108,8 +108,8 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) {
func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
- _, config := newTestChainScopedConfig(t)
+ db := testutils.NewSqlxDB(t)
+ config := configtest.NewChainScopedConfig(t, nil)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -186,7 +186,7 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) {
func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -294,7 +294,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) {
func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -396,7 +396,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) {
func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
@@ -488,7 +488,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) {
func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
ctx := tests.Context(t)
diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go
index 3d281aba8c7..ad90d985995 100644
--- a/core/chains/evm/txmgr/tracker_test.go
+++ b/core/chains/evm/txmgr/tracker_test.go
@@ -14,14 +14,14 @@ import (
"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/pgtest"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/keystore"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
func newTestEvmTrackerSetup(t *testing.T) (*txmgr.Tracker, txmgr.TestEvmTxStore, keystore.Eth, []common.Address) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
chainID := big.NewInt(0)
diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go
index aa07dbb08fc..001ead9255e 100644
--- a/core/chains/evm/txmgr/txmgr_test.go
+++ b/core/chains/evm/txmgr/txmgr_test.go
@@ -34,9 +34,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/internal/cltest"
- "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/evm/assets"
evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
"github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
@@ -93,7 +90,7 @@ func makeTestEvmTxm(
func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
from := utils.ZeroAddress
to := utils.ZeroAddress
@@ -116,7 +113,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) {
func TestTxm_CreateTransaction(t *testing.T) {
t.Parallel()
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
kst := cltest.NewKeyStore(t, db)
@@ -240,7 +237,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("simulate transmit checker", func(t *testing.T) {
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
checker := txmgr.TransmitCheckerSpec{
CheckerType: txmgr.TransmitCheckerTypeSimulate,
@@ -266,7 +263,7 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("meta and vrf checker", func(t *testing.T) {
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
testDefaultSubID := uint64(2)
testDefaultMaxLink := "1000000000000000000"
testDefaultMaxEth := "2000000000000000000"
@@ -314,8 +311,8 @@ func TestTxm_CreateTransaction(t *testing.T) {
})
t.Run("forwards tx when a proper forwarder is set up", func(t *testing.T) {
- pgtest.MustExec(t, db, `DELETE FROM evm.txes`)
- pgtest.MustExec(t, db, `DELETE FROM evm.forwarders`)
+ testutils.MustExec(t, db, `DELETE FROM evm.txes`)
+ testutils.MustExec(t, db, `DELETE FROM evm.forwarders`)
evmConfig.MaxQueued = uint64(1)
// Create mock forwarder, mock authorizedsenders call.
@@ -396,7 +393,7 @@ func newMockTxStrategy(t *testing.T) *commontxmmocks.TxStrategy {
}
func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
etKeyStore := cltest.NewKeyStore(t, db).Eth()
@@ -485,7 +482,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) {
}
func TestTxm_Lifecycle(t *testing.T) {
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
ethClient := clienttest.NewClientWithDefaultChainID(t)
kst := ksmocks.NewEth(t)
@@ -541,9 +538,9 @@ func TestTxm_Reset(t *testing.T) {
t.Parallel()
// Lots of boilerplate setup since we actually want to test start/stop of EthBroadcaster/EthConfirmer
- db := pgtest.NewSqlxDB(t)
- gcfg := configtest.NewTestGeneralConfig(t)
- cfg := evmtest.NewChainScopedConfig(t, gcfg)
+ db := testutils.NewSqlxDB(t)
+
+ _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
kst := cltest.NewKeyStore(t, db)
_, addr := cltest.RandomKey{}.MustInsert(t, kst.Eth())
@@ -559,14 +556,14 @@ func TestTxm_Reset(t *testing.T) {
}
ethClient := clienttest.NewClientWithDefaultChainID(t)
- ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil)
+ ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Maybe()
ethClient.On("BatchCallContextAll", mock.Anything, mock.Anything).Return(nil).Maybe()
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().ChainType(), ethClient.ConfiguredChainID(), cfg.EVM().GasEstimator(), nil)
+ estimator, err := gas.NewEstimator(logger.Test(t), ethClient, evmConfig.ChainType(), ethClient.ConfiguredChainID(), evmConfig.GasEstimator(), nil)
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())
+ txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), kst.Eth())
require.NoError(t, err)
cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, addr2)
@@ -608,12 +605,12 @@ func TestTxm_GetTransactionStatus(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- db := pgtest.NewSqlxDB(t)
+ db := testutils.NewSqlxDB(t)
txStore := cltest.NewTestTxStore(t, db)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
feeLimit := uint64(10_000)
- gcfg := configtest.NewTestGeneralConfig(t)
- cfg := evmtest.NewChainScopedConfig(t, gcfg)
+
+ _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
h99 := &evmtypes.Head{
Hash: utils.NewHash(),
@@ -626,7 +623,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) {
}
head.Parent.Store(h99)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(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.Load(), nil).Once()
@@ -635,7 +632,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) {
feeEstimator.On("Start", mock.Anything).Return(nil).Once()
feeEstimator.On("Close", mock.Anything).Return(nil).Once()
feeEstimator.On("OnNewLongestChain", mock.Anything, mock.Anything).Once()
- txm, err := makeTestEvmTxm(t, db, ethClient, feeEstimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), ethKeyStore)
+ txm, err := makeTestEvmTxm(t, db, ethClient, feeEstimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), ethKeyStore)
require.NoError(t, err)
servicetest.Run(t, txm)
diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go
index 721de61e770..8d3e2251bb0 100644
--- a/core/chains/legacyevm/chain.go
+++ b/core/chains/legacyevm/chain.go
@@ -125,12 +125,6 @@ func (e errChainDisabled) Error() string {
return fmt.Sprintf("cannot create new chain with ID %s, the chain is disabled", e.ChainID.String())
}
-// TODO BCF-2509 what is this and does it need the entire app config?
-type AppConfig interface {
- EVMRPCEnabled() bool
- toml.HasEVMConfigs
-}
-
type FeatureConfig interface {
LogPoller() bool
}
@@ -142,7 +136,7 @@ type ChainRelayOpts struct {
}
type ChainOpts struct {
- AppConfig AppConfig
+ ChainConfigs toml.EVMConfigs
DatabaseConfig txmgr.DatabaseConfig
FeatureConfig FeatureConfig
ListenerConfig txmgr.ListenerConfig
@@ -164,8 +158,8 @@ type ChainOpts struct {
func (o ChainOpts) Validate() error {
var err error
- if o.AppConfig == nil {
- err = errors.Join(err, errors.New("nil AppConfig"))
+ if o.ChainConfigs == nil {
+ err = errors.Join(err, errors.New("nil ChainConfigs"))
}
if o.DatabaseConfig == nil {
err = errors.Join(err, errors.New("nil DatabaseConfig"))
@@ -195,11 +189,10 @@ func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayOpt
return nil, err
}
chainID := chain.ChainID
- l := opts.Logger.With("evmChainID", chainID.String())
if !chain.IsEnabled() {
return nil, errChainDisabled{ChainID: chainID}
}
- cfg := config.NewTOMLChainScopedConfig(chain, l)
+ cfg := config.NewTOMLChainScopedConfig(chain)
// note: per-chain validation is not necessary at this point since everything is checked earlier on boot.
return newChain(ctx, cfg, chain.Nodes, opts, clientsByChainID)
}
@@ -209,7 +202,7 @@ func newChain(ctx context.Context, cfg *config.ChainScoped, nodes []*toml.Node,
l := opts.Logger
var cl client.Client
var err error
- if !opts.AppConfig.EVMRPCEnabled() {
+ if !opts.ChainConfigs.RPCEnabled() {
cl = client.NewNullClient(chainID, l)
} else if opts.GenEthClient == nil {
cl, err = client.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes, cfg.EVM().ChainType())
@@ -223,7 +216,7 @@ func newChain(ctx context.Context, cfg *config.ChainScoped, nodes []*toml.Node,
headBroadcaster := headtracker.NewHeadBroadcaster(l)
headSaver := headtracker.NullSaver
var headTracker httypes.HeadTracker
- if !opts.AppConfig.EVMRPCEnabled() {
+ if !opts.ChainConfigs.RPCEnabled() {
headTracker = headtracker.NullTracker
} else if opts.GenHeadTracker == nil {
var orm headtracker.ORM
@@ -267,7 +260,7 @@ func newChain(ctx context.Context, cfg *config.ChainScoped, nodes []*toml.Node,
// note: gas estimator is started as a part of the txm
var txm txmgr.TxManager
//nolint:gocritic // ignoring suggestion to convert to switch statement
- if !opts.AppConfig.EVMRPCEnabled() {
+ if !opts.ChainConfigs.RPCEnabled() {
txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)}
} else if !cfg.EVM().Transactions().Enabled() {
txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("TXM disabled for chain %d", chainID)}
@@ -287,13 +280,13 @@ func newChain(ctx context.Context, cfg *config.ChainScoped, nodes []*toml.Node,
}
var balanceMonitor monitor.BalanceMonitor
- if opts.AppConfig.EVMRPCEnabled() && cfg.EVM().BalanceMonitor().Enabled() {
+ if opts.ChainConfigs.RPCEnabled() && cfg.EVM().BalanceMonitor().Enabled() {
balanceMonitor = monitor.NewBalanceMonitor(cl, opts.KeyStore, l)
headBroadcaster.Subscribe(balanceMonitor)
}
var logBroadcaster log.Broadcaster
- if !opts.AppConfig.EVMRPCEnabled() {
+ if !opts.ChainConfigs.RPCEnabled() {
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)}
diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go
index be5a8b76917..16553c52c98 100644
--- a/core/chains/legacyevm/chain_test.go
+++ b/core/chains/legacyevm/chain_test.go
@@ -38,7 +38,7 @@ func TestChainOpts_Validate(t *testing.T) {
{
name: "valid",
opts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
diff --git a/core/cmd/shell.go b/core/cmd/shell.go
index 144bd4a953e..f182875d2da 100644
--- a/core/cmd/shell.go
+++ b/core/cmd/shell.go
@@ -257,7 +257,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G
evmFactoryCfg := chainlink.EVMFactoryConfig{
CSAETHKeystore: keyStore,
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go
index 331432299a8..5e86b17c575 100644
--- a/core/cmd/shell_local_test.go
+++ b/core/cmd/shell_local_test.go
@@ -9,12 +9,18 @@ import (
"testing"
"time"
+ gethTypes "github.com/ethereum/go-ethereum/core/types"
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "github.com/urfave/cli"
+
commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg"
"github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
"github.com/smartcontractkit/chainlink-framework/multinode"
- evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/capabilities"
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
@@ -30,18 +36,13 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks"
+ evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm"
"github.com/smartcontractkit/chainlink/v2/core/sessions/localauth"
"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/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/plugins"
-
- gethTypes "github.com/ethereum/go-ethereum/core/types"
- "github.com/google/uuid"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
- "github.com/urfave/cli"
)
func genTestEVMRelayers(t *testing.T, cfg chainlink.GeneralConfig, ds sqlutil.DataSource, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators {
@@ -54,7 +55,7 @@ func genTestEVMRelayers(t *testing.T, cfg chainlink.GeneralConfig, ds sqlutil.Da
relayers, err := chainlink.NewCoreRelayerChainInteroperators(chainlink.InitEVM(testutils.Context(t), f, chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
@@ -291,7 +292,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) {
app.On("GetKeyStore").Return(keyStore)
app.On("ID").Maybe().Return(uuid.New())
app.On("GetConfig").Return(config)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
mockRelayerChainInteroperators := &chainlinkmocks.FakeRelayerChainInteroperators{EVMChains: legacy}
@@ -373,7 +374,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) {
app.On("GetKeyStore").Return(keyStore)
app.On("ID").Maybe().Return(uuid.New())
app.On("GetConfig").Return(config)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("Dial", mock.Anything).Return(nil)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
@@ -451,7 +452,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) {
app.On("GetDB").Maybe().Return(sqlxDB)
app.On("GetKeyStore").Return(keyStore)
app.On("ID").Maybe().Return(uuid.New())
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
ethClient.On("Dial", mock.Anything).Return(nil)
legacy := cltest.NewLegacyChainsWithMockChain(t, ethClient, config)
diff --git a/core/config/app_config.go b/core/config/app_config.go
index 4ce8873bb96..d4ef27b6305 100644
--- a/core/config/app_config.go
+++ b/core/config/app_config.go
@@ -20,7 +20,6 @@ type AppConfig interface {
ShutdownGracePeriod() time.Duration
InsecureFastScrypt() bool
EVMEnabled() bool
- EVMRPCEnabled() bool
CosmosEnabled() bool
SolanaEnabled() bool
StarkNetEnabled() bool
diff --git a/core/gethwrappers/abigen_test.go b/core/gethwrappers/abigen_test.go
index 21858f67ee4..c4f7482db8a 100644
--- a/core/gethwrappers/abigen_test.go
+++ b/core/gethwrappers/abigen_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/log_emitter"
- "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/evm/testutils"
)
// Test that the generated Deploy method fill all the required fields and returns the correct address.
diff --git a/core/gethwrappers/ccip/generated/burn_to_address_mint_token_pool/burn_to_address_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_to_address_mint_token_pool/burn_to_address_mint_token_pool.go
new file mode 100644
index 00000000000..21fe8a26520
--- /dev/null
+++ b/core/gethwrappers/ccip/generated/burn_to_address_mint_token_pool/burn_to_address_mint_token_pool.go
@@ -0,0 +1,3209 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package burn_to_address_mint_token_pool
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
+)
+
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+type PoolLockOrBurnInV1 struct {
+ Receiver []byte
+ RemoteChainSelector uint64
+ OriginalSender common.Address
+ Amount *big.Int
+ LocalToken common.Address
+}
+
+type PoolLockOrBurnOutV1 struct {
+ DestTokenAddress []byte
+ DestPoolData []byte
+}
+
+type PoolReleaseOrMintInV1 struct {
+ OriginalSender []byte
+ RemoteChainSelector uint64
+ Receiver common.Address
+ Amount *big.Int
+ LocalToken common.Address
+ SourcePoolAddress []byte
+ SourcePoolData []byte
+ OffchainTokenData []byte
+}
+
+type PoolReleaseOrMintOutV1 struct {
+ DestinationAmount *big.Int
+}
+
+type RateLimiterConfig struct {
+ IsEnabled bool
+ Capacity *big.Int
+ Rate *big.Int
+}
+
+type RateLimiterTokenBucket struct {
+ Tokens *big.Int
+ LastUpdated uint32
+ IsEnabled bool
+ Capacity *big.Int
+ Rate *big.Int
+}
+
+type TokenPoolChainUpdate struct {
+ RemoteChainSelector uint64
+ RemotePoolAddresses [][]byte
+ RemoteTokenAddress []byte
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+}
+
+var BurnToAddressMintTokenPoolMetaData = &bind.MetaData{
+ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIBurnMintERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"burnAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBurnAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"burnAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"i_burnAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]",
+ Bin: "0x610120806040523461038257614bdb803803809161001d8285610401565b8339810160c0828203126103825781516001600160a01b03811692908390036103825761004c60208201610424565b60408201516001600160401b0381116103825782019280601f85011215610382578351936001600160401b0385116103eb578460051b9060208201956100956040519788610401565b865260208087019282010192831161038257602001905b8282106103d3575050506100c260608301610432565b936100db60a06100d460808601610432565b9401610432565b9433156103c257600180546001600160a01b03191633179055811580156103b1575b80156103a0575b61038f578160209160049360805260c0526040519283809263313ce56760e01b82525afa6000918161034e575b50610323575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e0819052610206575b50610100526040516145f490816105e7823960805181818161161701528181611809015281816123630152818161253f0152818161285101526128c9015260a05181818161196f015281816127d80152818161332d01526133b0015260c051818181610beb015281816116b301526123fe015260e051818181610b7b015281816116f6015261215a01526101005181818161185e0152612c420152f35b60206040516102158282610401565b60008152600036813760e051156103125760005b8151811015610290576001906001600160a01b036102478285610446565b51168461025382610488565b610260575b505001610229565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13884610258565b505060005b8251811015610309576001906001600160a01b036102b38286610446565b5116801561030357836102c582610586565b6102d3575b50505b01610295565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102ca565b506102cd565b50505038610169565b6335f4a7b360e01b60005260046000fd5b60ff1660ff82168181036103375750610137565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d602011610387575b8161036a60209383610401565b810103126103825761037b90610424565b9038610131565b600080fd5b3d915061035d565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b03811615610104565b506001600160a01b038416156100fd565b639b15e16f60e01b60005260046000fd5b602080916103e084610432565b8152019101906100ac565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103eb57604052565b519060ff8216820361038257565b51906001600160a01b038216820361038257565b805182101561045a5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561045a5760005260206000200190600090565b600081815260036020526040902054801561057f5760001981018181116105695760025460001981019190821161056957818103610518575b505050600254801561050257600019016104dc816002610470565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61055161052961053a936002610470565b90549060031b1c9283926002610470565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104c1565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105e057600254680100000000000000008110156103eb576105c761053a8260018594016002556002610470565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461296c57508063181f5a77146128ed57806321df0da71461287e578063240028e8146127fc57806324f65ee7146127a057806338b39d2914610dde57806339077537146122bd5780634c5ef0ed146122a357806354c8a4f31461212657806362ddd3c4146120a25780636d3d1a581461205057806379ba509714611f6b5780637d54534e14611ebe5780638926f54f14611e5a5780638da5cb5b14611e08578063962d402014611c645780639a4575b91461156f578063a42a7b8b146113ea578063a7cd63b71461131e578063acfecf91146111fa578063af58d59f14611193578063b0f479a114611141578063b7946580146110ea578063c0d7865514610ff2578063c4bffe2b14610ea9578063c75eea9c14610de3578063c8de9fe014610dde578063cf7401f314610c0f578063dc0bd97114610ba0578063e0351e1314610b45578063e8a1da17146102705763f2fde38b1461018157600080fd5b3461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5773ffffffffffffffffffffffffffffffffffffffff6101cd612bd4565b6101d56134ba565b1633811461024557807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b503461026d5761027f36612d31565b9391909261028b6134ba565b82915b8083106109b0575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b858210156109ac578160051b850135818112156109a857850190610120823603126109a857604051956102f987612ac2565b823567ffffffffffffffff811681036109a3578752602083013567ffffffffffffffff811161099f5783019536601f8801121561099f5786359661033c88612f2f565b9761034a604051998a612afa565b8089526020808a019160051b8301019036821161099b5760208301905b828210610968575050505060208801968752604084013567ffffffffffffffff81116109645761039a9036908601613287565b9860408901998a526103c46103b23660608801612def565b9560608b0196875260c0369101612def565b9660808a019788526103d68651613931565b6103e08851613931565b8a51511561093c576103fc67ffffffffffffffff8b5116614184565b156109055767ffffffffffffffff8a5116815260076020526040812061053c87516fffffffffffffffffffffffffffffffff604082015116906104f76fffffffffffffffffffffffffffffffff6020830151169151151583608060405161046281612ac2565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61066289516fffffffffffffffffffffffffffffffff6040820151169061061d6fffffffffffffffffffffffffffffffff6020830151169151151583608060405161058681612ac2565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108d8576106858354613027565b601f811161089d575b50602090601f83116001146107fe576106dc92918591836107f3575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b89518051821015610717579061071160019261070a838f67ffffffffffffffff90511692613013565b5190613505565b016106e1565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107e567ffffffffffffffff600197949c51169251935191516107b161077c60405196879687526101006020880152610100870190612b75565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102c7565b0151905038806106aa565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b818110610885575090846001959493921061084e575b505050811b0190556106df565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080610841565b9293602060018192878601518155019501930161082b565b6108c89084865260208620601f850160051c810191602086106108ce575b601f0160051c019061322e565b3861068e565b90915081906108bb565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109975760209161098c8392833691890101613287565b815201910190610367565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109d06109cb878588612faf565b612fee565b16956109db87613eb8565b15610b195786845260076020526109f760056040862001613cbf565b94845b8651811015610a30576001908987526007602052610a2960056040892001610a22838b613013565b5190613fe3565b50016109fa565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a698154613027565b80610ad8575b5050500180549086815581610aba575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a101919094939461028e565b865260208620908101905b81811015610a7f57868155600101610ac5565b601f8111600114610aee5750555b863880610a6f565b81835260208320610b0991601f01861c81019060010161322e565b8082528160208120915555610ae6565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461026d5760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57610c47612c66565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261026d57604051610c7e81612ade565b6024358015158103610dda5781526044356fffffffffffffffffffffffffffffffff81168103610dda5760208201526064356fffffffffffffffffffffffffffffffff81168103610dda57604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dd65760405190610d0582612ade565b60843580151581036109a857825260a4356fffffffffffffffffffffffffffffffff811681036109a857602083015260c4356fffffffffffffffffffffffffffffffff811681036109a857604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610db4575b610d8857610d85929361376f565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d77565b5080fd5b8280fd5b612bf7565b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57610e4c610e476040610ea59367ffffffffffffffff610e30612c66565b610e3861317b565b501681526007602052206131a6565b6138ac565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57604051906005548083528260208101600584526020842092845b818110610fd9575050610f0792500383612afa565b8151610f2b610f1582612f2f565b91610f236040519384612afa565b808352612f2f565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f8a578067ffffffffffffffff610f7760019388613013565b5116610f838286613013565b5201610f58565b50925090604051928392602084019060208552518091526040840192915b818110610fb6575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610fa8565b8454835260019485019487945060209093019201610ef2565b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5773ffffffffffffffffffffffffffffffffffffffff61103f612bd4565b6110476134ba565b1680156110c25760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57610ea561112d611128612c66565b61320c565b604051918291602083526020830190612b75565b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57610e4c610e4760026040610ea59467ffffffffffffffff6111e2612c66565b6111ea61317b565b50168152600760205220016131a6565b503461026d5767ffffffffffffffff61121236612c7d565b92909161121d6134ba565b1691611236836000526006602052604060002054151590565b156112f257828452600760205261126560056040862001611258368486612e8c565b6020815191012090613fe3565b156112aa57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76916112a460405192839260208452602084019161313c565b0390a280f35b826112ee836040519384937f74f23c7c000000000000000000000000000000000000000000000000000000008552600485015260406024850152604484019161313c565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57604051600254808252602082018091600285526020852090855b8181106113d4575050508261137d910383612afa565b604051928392602084019060208552518091526040840192915b8181106113a5575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611397565b8254845260209093019260019283019201611367565b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5767ffffffffffffffff61142b612c66565b168152600760205261144260056040832001613cbf565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061148761147183612f2f565b9261147f6040519485612afa565b808452612f2f565b01835b81811061155e575050825b82518110156114db57806114ab60019285613013565b51855260086020526114bf6040862061307a565b6114c98285613013565b526114d48184613013565b5001611495565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b82821061151357505050500390f35b9193602061154e827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186528851612b75565b9601920192018594939192611504565b80606060208093860101520161148a565b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5760043567ffffffffffffffff8111610dd65760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dd657606060206040516115ed81612aa6565b8281520152608481016115ff81612ec3565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611c1a5750602481019077ffffffffffffffff0000000000000000000000000000000061166683612fee565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611b3b578491611beb575b50611bc3576116f460448201612ec3565b7f0000000000000000000000000000000000000000000000000000000000000000611b71575b5067ffffffffffffffff61172d83612fee565b16611745816000526006602052604060002054151590565b15611b4657602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa8015611b3b578490611ad8575b73ffffffffffffffffffffffffffffffffffffffff9150163303611aac57611920829360646117dd67ffffffffffffffff95612fee565b93013593849316815260076020526118316040822073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016958691614233565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082019081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16602483015260448083018690528252949091906118b1606484612afa565b81806040978851956118c38a88612afa565b602087527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020880152519082855af1903d15611aa3573d61190481612b3b565b9061191189519283612afa565b8152809360203d92013e61451b565b805180611a02575b6119d184610ea5611967611128898885519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612fee565b9180519060ff7f0000000000000000000000000000000000000000000000000000000000000000166020830152602082526119a28183612afa565b8051936119ae85612aa6565b845260208401918252805194859460208652518260208701526060860190612b75565b9151907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08584030190850152612b75565b90602080611a149383010191016132a2565b15611a20573880611928565b608482517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6060925061451b565b6024837f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b506020813d602011611b33575b81611af260209383612afa565b810103126109a8575173ffffffffffffffffffffffffffffffffffffffff811681036109a85773ffffffffffffffffffffffffffffffffffffffff906117a6565b3d9150611ae5565b6040513d86823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008452600452602483fd5b73ffffffffffffffffffffffffffffffffffffffff168084526003602052604084205461171a577fd0d25976000000000000000000000000000000000000000000000000000000008452600452602483fd5b6004837f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b611c0d915060203d602011611c13575b611c058183612afa565b8101906132a2565b386116e3565b503d611bfb565b8273ffffffffffffffffffffffffffffffffffffffff611c3b602493612ec3565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b503461026d5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5760043567ffffffffffffffff8111610dd657611cb4903690600401612d00565b60243567ffffffffffffffff81116109a857611cd4903690600401612da1565b60449291923567ffffffffffffffff811161099f57611cf7903690600401612da1565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611de6575b611dba57818114801590611db0575b611d8857865b818110611d3c578780f35b80611d82611d506109cb600194868c612faf565b611d5b83878b613003565b611d7c611d74611d6c868b8d613003565b923690612def565b913690612def565b9161376f565b01611d31565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611d2b565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611d1c565b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d576020611eb467ffffffffffffffff611ea0612c66565b166000526006602052604060002054151590565b6040519015158152f35b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611f2e612bd4565b611f366134ba565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57805473ffffffffffffffffffffffffffffffffffffffff81163303612028577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461026d576120b136612c7d565b6120bd939291936134ba565b67ffffffffffffffff82166120df816000526006602052604060002054151590565b156120fb5750610d8592936120f5913691612e8c565b90613505565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461026d576121509061215861213c36612d31565b95916121499391936134ba565b3691612f47565b933691612f47565b7f00000000000000000000000000000000000000000000000000000000000000001561227b57815b83518110156121f3578073ffffffffffffffffffffffffffffffffffffffff6121ab60019387613013565b51166121b681613d22565b6121c2575b5001612180565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1386121bb565b5090805b8251811015612277578073ffffffffffffffffffffffffffffffffffffffff61222260019386613013565b511680156122715761223381614124565b612240575b505b016121f7565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a184612238565b5061223a565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b503461026d576020611eb46122b736612c7d565b91612ee4565b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5760043567ffffffffffffffff8111610dd657806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dda578260405161233d81612a5b565b526084820161234b81612ec3565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361277f57506024820177ffffffffffffffff000000000000000000000000000000006123b182612fee565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115612702578591612760575b506127385767ffffffffffffffff61244582612fee565b1661245d816000526006602052604060002054151590565b1561270d57602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156127025785916126e3575b50156126b7576124d481612fee565b6124e660a48501916122b78386612e3b565b15612670575061258367ffffffffffffffff9261257d61257861257161250d604496612fee565b936064890135978895168a526007602052612567600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a91614233565b60c4890190612e3b565b3691612e8c565b6132ba565b906133ad565b9201908361259083612ec3565b823b15610dd6576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101859052918290604490829084905af18015611b3b579160209461261e9273ffffffffffffffffffffffffffffffffffffffff94612660575b5050612ec3565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a38060405161265781612a5b565b52604051908152f35b8161266a91612afa565b38612617565b61267a9083612e3b565b6112ee6040519283927f24eb47e500000000000000000000000000000000000000000000000000000000845260206004850152602484019161313c565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6126fc915060203d602011611c1357611c058183612afa565b386124c5565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b612779915060203d602011611c1357611c058183612afa565b3861242e565b8373ffffffffffffffffffffffffffffffffffffffff611c3b602493612ec3565b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461026d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602090612837612bd4565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461026d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261026d5750610ea560405161292e604082612afa565b601c81527f4275726e546f41646472657373546f6b656e506f6f6c20312e352e31000000006020820152604051918291602083526020830190612b75565b905034610dd65760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dd6576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dda57602092507faff2afbf000000000000000000000000000000000000000000000000000000008114908115612a31575b8115612a07575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438612a00565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506129f9565b6020810190811067ffffffffffffffff821117612a7757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117612a7757604052565b60a0810190811067ffffffffffffffff821117612a7757604052565b6060810190811067ffffffffffffffff821117612a7757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612a7757604052565b67ffffffffffffffff8111612a7757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b848110612bbf5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201612b80565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036109a357565b346109a35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109a357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359067ffffffffffffffff821682036109a357565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126109a35760043567ffffffffffffffff811681036109a3579160243567ffffffffffffffff81116109a357826023820112156109a35780600401359267ffffffffffffffff84116109a357602484830101116109a3576024019190565b9181601f840112156109a35782359167ffffffffffffffff83116109a3576020808501948460051b0101116109a357565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126109a35760043567ffffffffffffffff81116109a35781612d7a91600401612d00565b929092916024359067ffffffffffffffff82116109a357612d9d91600401612d00565b9091565b9181601f840112156109a35782359167ffffffffffffffff83116109a357602080850194606085020101116109a357565b35906fffffffffffffffffffffffffffffffff821682036109a357565b91908260609103126109a357604051612e0781612ade565b809280359081151582036109a3576040612e369181938552612e2b60208201612dd2565b602086015201612dd2565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156109a3570180359067ffffffffffffffff82116109a3576020019181360383136109a357565b929192612e9882612b3b565b91612ea66040519384612afa565b8294818452818301116109a3578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff811681036109a35790565b612f2c929167ffffffffffffffff612f0f921660005260076020526005604060002001923691612e8c565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff8111612a775760051b60200190565b9291612f5282612f2f565b93612f606040519586612afa565b602085848152019260051b81019182116109a357915b818310612f8257505050565b823573ffffffffffffffffffffffffffffffffffffffff811681036109a357815260209283019201612f76565b9190811015612fbf5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff811681036109a35790565b9190811015612fbf576060020190565b8051821015612fbf5760209160051b010190565b90600182811c92168015613070575b602083101461304157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691613036565b906040519182600082549261308e84613027565b80845293600181169081156130fc57506001146130b5575b506130b392500383612afa565b565b90506000929192526020600020906000915b8183106130e05750509060206130b392820101386130a6565b60209193508060019154838589010152019101909184926130c7565b602093506130b39592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b820101386130a6565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b6040519061318882612ac2565b60006080838281528260208201528260408201528260608201520152565b906040516131b381612ac2565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612f2c600460406000200161307a565b818110613239575050565b6000815560010161322e565b8181029291811591840414171561325857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f830112156109a357816020612f2c93359101612e8c565b908160209103126109a3575180151581036109a35790565b80518015613329576020036132eb576020818051810103126109a35760208101519060ff82116132eb575060ff1690565b6112ee906040519182917f953576f7000000000000000000000000000000000000000000000000000000008352602060048401526024830190612b75565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161325857565b60ff16604d811161325857600a0a90565b811561337e570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146134b35782841161348957906133f29161334f565b91604d60ff8416118015613450575b61341a57505090613414612f2c92613363565b90613245565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b5061345a83613363565b801561337e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411613401565b6134929161334f565b91604d60ff84161161341a575050906134ad612f2c92613363565b90613374565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff6001541633036134db57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156137455767ffffffffffffffff8151602083012092169182600052600760205261353a8160056040600020016141de565b156137015760005260086020526040600020815167ffffffffffffffff8111612a77576135678254613027565b601f81116136cf575b506020601f821160011461360957916135e3827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea95936135f9956000916135fe575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055604051918291602083526020830190612b75565b0390a2565b9050840151386135b2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106136b75750926135f99492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea989610613680575b5050811b01905561112d565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880613674565b9192602060018192868a015181550194019201613639565b6136fb90836000526020600020601f840160051c810191602085106108ce57601f0160051c019061322e565b38613570565b50906112ee6040519283927f393b8ad20000000000000000000000000000000000000000000000000000000084526004840152604060248401526044830190612b75565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff166000818152600660205260409020549092919015613871579161386e60e09261383a856137c67f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b97613931565b8460005260076020526137dd816040600020613a8c565b6137e683613931565b846000526007602052613800836002604060002001613a8c565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161325857565b6138b461317b565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff8083511691613911602085019361390b6138fe63ffffffff8751164261389f565b8560808901511690613245565b90614117565b8082101561392a57505b16825263ffffffff4216905290565b905061391b565b8051156139e5576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff6020830151168110908115916139dc575b506139795750565b6064906139da604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b90501538613971565b6fffffffffffffffffffffffffffffffff60408201511615801590613a6d575b613a0c5750565b6064906139da604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613a05565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1991613bc56060928054613ac963ffffffff8260801c164261389f565b9081613c04575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613bfc57508280855b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416178155613b798651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b61386e60405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b838091613b00565b6fffffffffffffffffffffffffffffffff91613c39839283613c326001880154948286169560801c90613245565b9116614117565b80821015613cb857505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff00000000000000000000000000000000161781553880613ad0565b9050613c43565b906040519182815491828252602082019060005260206000209260005b818110613cf15750506130b392500383612afa565b8454835260019485019487945060209093019201613cdc565b8054821015612fbf5760005260206000200190600090565b6000818152600360205260409020548015613eb1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161325857600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161325857818103613e42575b5050506002548015613e13577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613dd0816002613d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613e99613e53613e64936002613d0a565b90549060031b1c9283926002613d0a565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613d97565b5050600090565b6000818152600660205260409020548015613eb1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161325857600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161325857818103613fa9575b5050506005548015613e13577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613f66816005613d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613fcb613fba613e64936005613d0a565b90549060031b1c9283926005613d0a565b90556000526006602052604060002055388080613f2d565b906001820191816000528260205260406000205480151560001461410e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613258578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211613258578181036140d7575b50505080548015613e13577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906140988282613d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b6140f76140e7613e649386613d0a565b90549060031b1c92839286613d0a565b905560005283602052604060002055388080614060565b50505050600090565b9190820180921161325857565b8060005260036020526040600020541560001461417e5760025468010000000000000000811015612a7757614165613e648260018594016002556002613d0a565b9055600254906000526003602052604060002055600190565b50600090565b8060005260066020526040600020541560001461417e5760055468010000000000000000811015612a77576141c5613e648260018594016005556005613d0a565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613eb15780549068010000000000000000821015612a77578261421c613e64846001809601855584613d0a565b905580549260005201602052604060002055600190565b929192805460ff8160a01c16158015614513575b61450c576fffffffffffffffffffffffffffffffff8116906001830190815461428c63ffffffff6fffffffffffffffffffffffffffffffff83169360801c164261389f565b908161446e575b50508481106143ec575083821061431b57507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff806142e9856020969561389f565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061432d92505460801c9261389f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908082116132585761437b6143809273ffffffffffffffffffffffffffffffffffffffff94614117565b613374565b92169182156143bc577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff881691821561443e577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8285929395116144e2576144899261390b9160801c90613245565b808310156144dd5750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff0000000000000000000000000000000016178455913880614293565b614494565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b508215614247565b91929015614596575081511561452f575090565b3b156145385790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156145a95750805190602001fd5b6112ee906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190612b7556fea164736f6c634300081a000a",
+}
+
+var BurnToAddressMintTokenPoolABI = BurnToAddressMintTokenPoolMetaData.ABI
+
+var BurnToAddressMintTokenPoolBin = BurnToAddressMintTokenPoolMetaData.Bin
+
+func DeployBurnToAddressMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address, burnAddress common.Address) (common.Address, *types.Transaction, *BurnToAddressMintTokenPool, error) {
+ parsed, err := BurnToAddressMintTokenPoolMetaData.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(BurnToAddressMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router, burnAddress)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &BurnToAddressMintTokenPool{address: address, abi: *parsed, BurnToAddressMintTokenPoolCaller: BurnToAddressMintTokenPoolCaller{contract: contract}, BurnToAddressMintTokenPoolTransactor: BurnToAddressMintTokenPoolTransactor{contract: contract}, BurnToAddressMintTokenPoolFilterer: BurnToAddressMintTokenPoolFilterer{contract: contract}}, nil
+}
+
+type BurnToAddressMintTokenPool struct {
+ address common.Address
+ abi abi.ABI
+ BurnToAddressMintTokenPoolCaller
+ BurnToAddressMintTokenPoolTransactor
+ BurnToAddressMintTokenPoolFilterer
+}
+
+type BurnToAddressMintTokenPoolCaller struct {
+ contract *bind.BoundContract
+}
+
+type BurnToAddressMintTokenPoolTransactor struct {
+ contract *bind.BoundContract
+}
+
+type BurnToAddressMintTokenPoolFilterer struct {
+ contract *bind.BoundContract
+}
+
+type BurnToAddressMintTokenPoolSession struct {
+ Contract *BurnToAddressMintTokenPool
+ CallOpts bind.CallOpts
+ TransactOpts bind.TransactOpts
+}
+
+type BurnToAddressMintTokenPoolCallerSession struct {
+ Contract *BurnToAddressMintTokenPoolCaller
+ CallOpts bind.CallOpts
+}
+
+type BurnToAddressMintTokenPoolTransactorSession struct {
+ Contract *BurnToAddressMintTokenPoolTransactor
+ TransactOpts bind.TransactOpts
+}
+
+type BurnToAddressMintTokenPoolRaw struct {
+ Contract *BurnToAddressMintTokenPool
+}
+
+type BurnToAddressMintTokenPoolCallerRaw struct {
+ Contract *BurnToAddressMintTokenPoolCaller
+}
+
+type BurnToAddressMintTokenPoolTransactorRaw struct {
+ Contract *BurnToAddressMintTokenPoolTransactor
+}
+
+func NewBurnToAddressMintTokenPool(address common.Address, backend bind.ContractBackend) (*BurnToAddressMintTokenPool, error) {
+ abi, err := abi.JSON(strings.NewReader(BurnToAddressMintTokenPoolABI))
+ if err != nil {
+ return nil, err
+ }
+ contract, err := bindBurnToAddressMintTokenPool(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPool{address: address, abi: abi, BurnToAddressMintTokenPoolCaller: BurnToAddressMintTokenPoolCaller{contract: contract}, BurnToAddressMintTokenPoolTransactor: BurnToAddressMintTokenPoolTransactor{contract: contract}, BurnToAddressMintTokenPoolFilterer: BurnToAddressMintTokenPoolFilterer{contract: contract}}, nil
+}
+
+func NewBurnToAddressMintTokenPoolCaller(address common.Address, caller bind.ContractCaller) (*BurnToAddressMintTokenPoolCaller, error) {
+ contract, err := bindBurnToAddressMintTokenPool(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolCaller{contract: contract}, nil
+}
+
+func NewBurnToAddressMintTokenPoolTransactor(address common.Address, transactor bind.ContractTransactor) (*BurnToAddressMintTokenPoolTransactor, error) {
+ contract, err := bindBurnToAddressMintTokenPool(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolTransactor{contract: contract}, nil
+}
+
+func NewBurnToAddressMintTokenPoolFilterer(address common.Address, filterer bind.ContractFilterer) (*BurnToAddressMintTokenPoolFilterer, error) {
+ contract, err := bindBurnToAddressMintTokenPool(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolFilterer{contract: contract}, nil
+}
+
+func bindBurnToAddressMintTokenPool(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := BurnToAddressMintTokenPoolMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BurnToAddressMintTokenPool.Contract.BurnToAddressMintTokenPoolCaller.contract.Call(opts, result, method, params...)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.BurnToAddressMintTokenPoolTransactor.contract.Transfer(opts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.BurnToAddressMintTokenPoolTransactor.contract.Transact(opts, method, params...)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _BurnToAddressMintTokenPool.Contract.contract.Call(opts, result, method, params...)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.contract.Transfer(opts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.contract.Transact(opts, method, params...)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetAllowList() ([]common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetAllowList(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetAllowList() ([]common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetAllowList(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "getAllowListEnabled")
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetAllowListEnabled() (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetAllowListEnabled(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetAllowListEnabled() (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetAllowListEnabled(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetBurnAddress(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "getBurnAddress")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetBurnAddress() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetBurnAddress(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetBurnAddress() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetBurnAddress(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetCurrentInboundRateLimiterState(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetCurrentInboundRateLimiterState(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetRateLimitAdmin() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRateLimitAdmin(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRateLimitAdmin(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector)
+
+ if err != nil {
+ return *new([][]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRemotePools(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRemotePools(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRemoteToken(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRemoteToken(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetRmnProxy(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetRmnProxy() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRmnProxy(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetRmnProxy() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRmnProxy(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetRouter() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRouter(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetRouter() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetRouter(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "getSupportedChains")
+
+ if err != nil {
+ return *new([]uint64), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetSupportedChains() ([]uint64, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetSupportedChains(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetSupportedChains() ([]uint64, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetSupportedChains(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetToken(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetToken() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetToken(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetToken() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetToken(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "getTokenDecimals")
+
+ if err != nil {
+ return *new(uint8), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) GetTokenDecimals() (uint8, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetTokenDecimals(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) {
+ return _BurnToAddressMintTokenPool.Contract.GetTokenDecimals(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) IBurnAddress(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "i_burnAddress")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) IBurnAddress() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.IBurnAddress(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) IBurnAddress() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.IBurnAddress(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress)
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsRemotePool(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsRemotePool(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsSupportedChain(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsSupportedChain(&_BurnToAddressMintTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) IsSupportedToken(token common.Address) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsSupportedToken(&_BurnToAddressMintTokenPool.CallOpts, token)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) IsSupportedToken(token common.Address) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.IsSupportedToken(&_BurnToAddressMintTokenPool.CallOpts, token)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) Owner(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) Owner() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.Owner(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) Owner() (common.Address, error) {
+ return _BurnToAddressMintTokenPool.Contract.Owner(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) SupportsInterface(interfaceId [4]byte) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.SupportsInterface(&_BurnToAddressMintTokenPool.CallOpts, interfaceId)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) {
+ return _BurnToAddressMintTokenPool.Contract.SupportsInterface(&_BurnToAddressMintTokenPool.CallOpts, interfaceId)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _BurnToAddressMintTokenPool.contract.Call(opts, &out, "typeAndVersion")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) TypeAndVersion() (string, error) {
+ return _BurnToAddressMintTokenPool.Contract.TypeAndVersion(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolCallerSession) TypeAndVersion() (string, error) {
+ return _BurnToAddressMintTokenPool.Contract.TypeAndVersion(&_BurnToAddressMintTokenPool.CallOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "acceptOwnership")
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) AcceptOwnership() (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.AcceptOwnership(&_BurnToAddressMintTokenPool.TransactOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) AcceptOwnership() (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.AcceptOwnership(&_BurnToAddressMintTokenPool.TransactOpts)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.AddRemotePool(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.AddRemotePool(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnToAddressMintTokenPool.TransactOpts, removes, adds)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnToAddressMintTokenPool.TransactOpts, removes, adds)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ApplyChainUpdates(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ApplyChainUpdates(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "lockOrBurn", lockOrBurnIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.LockOrBurn(&_BurnToAddressMintTokenPool.TransactOpts, lockOrBurnIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.LockOrBurn(&_BurnToAddressMintTokenPool.TransactOpts, lockOrBurnIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "releaseOrMint", releaseOrMintIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ReleaseOrMint(&_BurnToAddressMintTokenPool.TransactOpts, releaseOrMintIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.ReleaseOrMint(&_BurnToAddressMintTokenPool.TransactOpts, releaseOrMintIn)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.RemoveRemotePool(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.RemoveRemotePool(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnToAddressMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetRateLimitAdmin(&_BurnToAddressMintTokenPool.TransactOpts, rateLimitAdmin)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetRateLimitAdmin(&_BurnToAddressMintTokenPool.TransactOpts, rateLimitAdmin)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "setRouter", newRouter)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) SetRouter(newRouter common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetRouter(&_BurnToAddressMintTokenPool.TransactOpts, newRouter)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) SetRouter(newRouter common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.SetRouter(&_BurnToAddressMintTokenPool.TransactOpts, newRouter)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.contract.Transact(opts, "transferOwnership", to)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolSession) TransferOwnership(to common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.TransferOwnership(&_BurnToAddressMintTokenPool.TransactOpts, to)
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) {
+ return _BurnToAddressMintTokenPool.Contract.TransferOwnership(&_BurnToAddressMintTokenPool.TransactOpts, to)
+}
+
+type BurnToAddressMintTokenPoolAllowListAddIterator struct {
+ Event *BurnToAddressMintTokenPoolAllowListAdd
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListAddIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolAllowListAdd)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolAllowListAdd)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListAddIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListAddIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolAllowListAdd struct {
+ Sender common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolAllowListAddIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "AllowListAdd")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolAllowListAddIterator{contract: _BurnToAddressMintTokenPool.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolAllowListAdd) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolAllowListAdd)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseAllowListAdd(log types.Log) (*BurnToAddressMintTokenPoolAllowListAdd, error) {
+ event := new(BurnToAddressMintTokenPoolAllowListAdd)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "AllowListAdd", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolAllowListRemoveIterator struct {
+ Event *BurnToAddressMintTokenPoolAllowListRemove
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListRemoveIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolAllowListRemove)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolAllowListRemove)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListRemoveIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolAllowListRemoveIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolAllowListRemove struct {
+ Sender common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolAllowListRemoveIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "AllowListRemove")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolAllowListRemoveIterator{contract: _BurnToAddressMintTokenPool.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolAllowListRemove) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolAllowListRemove)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseAllowListRemove(log types.Log) (*BurnToAddressMintTokenPoolAllowListRemove, error) {
+ event := new(BurnToAddressMintTokenPoolAllowListRemove)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "AllowListRemove", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolBurnedIterator struct {
+ Event *BurnToAddressMintTokenPoolBurned
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolBurnedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolBurned)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolBurned)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolBurnedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolBurnedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolBurned struct {
+ Sender common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnToAddressMintTokenPoolBurnedIterator, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "Burned", senderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolBurnedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "Burned", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolBurned, sender []common.Address) (event.Subscription, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolBurned)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseBurned(log types.Log) (*BurnToAddressMintTokenPoolBurned, error) {
+ event := new(BurnToAddressMintTokenPoolBurned)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "Burned", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolChainAddedIterator struct {
+ Event *BurnToAddressMintTokenPoolChainAdded
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolChainAddedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolChainAddedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolChainAddedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolChainAdded struct {
+ RemoteChainSelector uint64
+ RemoteToken []byte
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterChainAdded(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainAddedIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "ChainAdded")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolChainAddedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "ChainAdded", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainAdded) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolChainAdded)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseChainAdded(log types.Log) (*BurnToAddressMintTokenPoolChainAdded, error) {
+ event := new(BurnToAddressMintTokenPoolChainAdded)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "ChainAdded", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolChainConfiguredIterator struct {
+ Event *BurnToAddressMintTokenPoolChainConfigured
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolChainConfiguredIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainConfigured)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainConfigured)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolChainConfiguredIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolChainConfiguredIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolChainConfigured struct {
+ RemoteChainSelector uint64
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterChainConfigured(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainConfiguredIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "ChainConfigured")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolChainConfiguredIterator{contract: _BurnToAddressMintTokenPool.contract, event: "ChainConfigured", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainConfigured) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolChainConfigured)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseChainConfigured(log types.Log) (*BurnToAddressMintTokenPoolChainConfigured, error) {
+ event := new(BurnToAddressMintTokenPoolChainConfigured)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "ChainConfigured", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolChainRemovedIterator struct {
+ Event *BurnToAddressMintTokenPoolChainRemoved
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolChainRemovedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolChainRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolChainRemovedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolChainRemovedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolChainRemoved struct {
+ RemoteChainSelector uint64
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterChainRemoved(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainRemovedIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "ChainRemoved")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolChainRemovedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "ChainRemoved", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainRemoved) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolChainRemoved)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseChainRemoved(log types.Log) (*BurnToAddressMintTokenPoolChainRemoved, error) {
+ event := new(BurnToAddressMintTokenPoolChainRemoved)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "ChainRemoved", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolConfigChangedIterator struct {
+ Event *BurnToAddressMintTokenPoolConfigChanged
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolConfigChangedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolConfigChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolConfigChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolConfigChangedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolConfigChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolConfigChanged struct {
+ Config RateLimiterConfig
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolConfigChangedIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "ConfigChanged")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolConfigChangedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolConfigChanged) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolConfigChanged)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseConfigChanged(log types.Log) (*BurnToAddressMintTokenPoolConfigChanged, error) {
+ event := new(BurnToAddressMintTokenPoolConfigChanged)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "ConfigChanged", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolLockedIterator struct {
+ Event *BurnToAddressMintTokenPoolLocked
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolLockedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolLocked)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolLocked)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolLockedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolLockedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolLocked struct {
+ Sender common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnToAddressMintTokenPoolLockedIterator, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "Locked", senderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolLockedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "Locked", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolLocked, sender []common.Address) (event.Subscription, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolLocked)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseLocked(log types.Log) (*BurnToAddressMintTokenPoolLocked, error) {
+ event := new(BurnToAddressMintTokenPoolLocked)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "Locked", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolMintedIterator struct {
+ Event *BurnToAddressMintTokenPoolMinted
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolMintedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolMinted)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolMinted)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolMintedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolMintedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolMinted struct {
+ Sender common.Address
+ Recipient common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnToAddressMintTokenPoolMintedIterator, 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 := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "Minted", senderRule, recipientRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolMintedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "Minted", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolMinted, 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 := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolMinted)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseMinted(log types.Log) (*BurnToAddressMintTokenPoolMinted, error) {
+ event := new(BurnToAddressMintTokenPoolMinted)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "Minted", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator struct {
+ Event *BurnToAddressMintTokenPoolOwnershipTransferRequested
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolOwnershipTransferRequested)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolOwnershipTransferRequested)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolOwnershipTransferRequested struct {
+ From common.Address
+ To common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator, 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 := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolOwnershipTransferRequested, 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 := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolOwnershipTransferRequested)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseOwnershipTransferRequested(log types.Log) (*BurnToAddressMintTokenPoolOwnershipTransferRequested, error) {
+ event := new(BurnToAddressMintTokenPoolOwnershipTransferRequested)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolOwnershipTransferredIterator struct {
+ Event *BurnToAddressMintTokenPoolOwnershipTransferred
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferredIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferredIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolOwnershipTransferredIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolOwnershipTransferred struct {
+ From common.Address
+ To common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnToAddressMintTokenPoolOwnershipTransferredIterator, 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 := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolOwnershipTransferredIterator{contract: _BurnToAddressMintTokenPool.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolOwnershipTransferred, 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 := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolOwnershipTransferred)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseOwnershipTransferred(log types.Log) (*BurnToAddressMintTokenPoolOwnershipTransferred, error) {
+ event := new(BurnToAddressMintTokenPoolOwnershipTransferred)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolRateLimitAdminSetIterator struct {
+ Event *BurnToAddressMintTokenPoolRateLimitAdminSet
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolRateLimitAdminSetIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRateLimitAdminSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRateLimitAdminSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolRateLimitAdminSetIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolRateLimitAdminSetIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolRateLimitAdminSet struct {
+ RateLimitAdmin common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolRateLimitAdminSetIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolRateLimitAdminSetIterator{contract: _BurnToAddressMintTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRateLimitAdminSet) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(BurnToAddressMintTokenPoolRateLimitAdminSet)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*BurnToAddressMintTokenPoolRateLimitAdminSet, error) {
+ event := new(BurnToAddressMintTokenPoolRateLimitAdminSet)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolReleasedIterator struct {
+ Event *BurnToAddressMintTokenPoolReleased
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolReleasedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolReleased)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolReleased)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolReleasedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolReleasedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolReleased struct {
+ Sender common.Address
+ Recipient common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnToAddressMintTokenPoolReleasedIterator, 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 := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "Released", senderRule, recipientRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolReleasedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "Released", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolReleased, 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 := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolReleased)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseReleased(log types.Log) (*BurnToAddressMintTokenPoolReleased, error) {
+ event := new(BurnToAddressMintTokenPoolReleased)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "Released", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolRemotePoolAddedIterator struct {
+ Event *BurnToAddressMintTokenPoolRemotePoolAdded
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolAddedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRemotePoolAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRemotePoolAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolAddedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolAddedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolRemotePoolAdded struct {
+ RemoteChainSelector uint64
+ RemotePoolAddress []byte
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnToAddressMintTokenPoolRemotePoolAddedIterator, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolRemotePoolAddedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(BurnToAddressMintTokenPoolRemotePoolAdded)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnToAddressMintTokenPoolRemotePoolAdded, error) {
+ event := new(BurnToAddressMintTokenPoolRemotePoolAdded)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolRemotePoolRemovedIterator struct {
+ Event *BurnToAddressMintTokenPoolRemotePoolRemoved
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolRemovedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRemotePoolRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRemotePoolRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolRemovedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolRemotePoolRemovedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolRemotePoolRemoved struct {
+ RemoteChainSelector uint64
+ RemotePoolAddress []byte
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnToAddressMintTokenPoolRemotePoolRemovedIterator, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolRemotePoolRemovedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(BurnToAddressMintTokenPoolRemotePoolRemoved)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnToAddressMintTokenPoolRemotePoolRemoved, error) {
+ event := new(BurnToAddressMintTokenPoolRemotePoolRemoved)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolRouterUpdatedIterator struct {
+ Event *BurnToAddressMintTokenPoolRouterUpdated
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolRouterUpdatedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRouterUpdated)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolRouterUpdated)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolRouterUpdatedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolRouterUpdatedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolRouterUpdated struct {
+ OldRouter common.Address
+ NewRouter common.Address
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolRouterUpdatedIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "RouterUpdated")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolRouterUpdatedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "RouterUpdated", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRouterUpdated) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolRouterUpdated)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseRouterUpdated(log types.Log) (*BurnToAddressMintTokenPoolRouterUpdated, error) {
+ event := new(BurnToAddressMintTokenPoolRouterUpdated)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "RouterUpdated", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type BurnToAddressMintTokenPoolTokensConsumedIterator struct {
+ Event *BurnToAddressMintTokenPoolTokensConsumed
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *BurnToAddressMintTokenPoolTokensConsumedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolTokensConsumed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(BurnToAddressMintTokenPoolTokensConsumed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *BurnToAddressMintTokenPoolTokensConsumedIterator) Error() error {
+ return it.fail
+}
+
+func (it *BurnToAddressMintTokenPoolTokensConsumedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type BurnToAddressMintTokenPoolTokensConsumed struct {
+ Tokens *big.Int
+ Raw types.Log
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolTokensConsumedIterator, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.contract.FilterLogs(opts, "TokensConsumed")
+ if err != nil {
+ return nil, err
+ }
+ return &BurnToAddressMintTokenPoolTokensConsumedIterator{contract: _BurnToAddressMintTokenPool.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolTokensConsumed) (event.Subscription, error) {
+
+ logs, sub, err := _BurnToAddressMintTokenPool.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(BurnToAddressMintTokenPoolTokensConsumed)
+ if err := _BurnToAddressMintTokenPool.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 (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPoolFilterer) ParseTokensConsumed(log types.Log) (*BurnToAddressMintTokenPoolTokensConsumed, error) {
+ event := new(BurnToAddressMintTokenPoolTokensConsumed)
+ if err := _BurnToAddressMintTokenPool.contract.UnpackLog(event, "TokensConsumed", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPool) ParseLog(log types.Log) (generated.AbigenLog, error) {
+ switch log.Topics[0] {
+ case _BurnToAddressMintTokenPool.abi.Events["AllowListAdd"].ID:
+ return _BurnToAddressMintTokenPool.ParseAllowListAdd(log)
+ case _BurnToAddressMintTokenPool.abi.Events["AllowListRemove"].ID:
+ return _BurnToAddressMintTokenPool.ParseAllowListRemove(log)
+ case _BurnToAddressMintTokenPool.abi.Events["Burned"].ID:
+ return _BurnToAddressMintTokenPool.ParseBurned(log)
+ case _BurnToAddressMintTokenPool.abi.Events["ChainAdded"].ID:
+ return _BurnToAddressMintTokenPool.ParseChainAdded(log)
+ case _BurnToAddressMintTokenPool.abi.Events["ChainConfigured"].ID:
+ return _BurnToAddressMintTokenPool.ParseChainConfigured(log)
+ case _BurnToAddressMintTokenPool.abi.Events["ChainRemoved"].ID:
+ return _BurnToAddressMintTokenPool.ParseChainRemoved(log)
+ case _BurnToAddressMintTokenPool.abi.Events["ConfigChanged"].ID:
+ return _BurnToAddressMintTokenPool.ParseConfigChanged(log)
+ case _BurnToAddressMintTokenPool.abi.Events["Locked"].ID:
+ return _BurnToAddressMintTokenPool.ParseLocked(log)
+ case _BurnToAddressMintTokenPool.abi.Events["Minted"].ID:
+ return _BurnToAddressMintTokenPool.ParseMinted(log)
+ case _BurnToAddressMintTokenPool.abi.Events["OwnershipTransferRequested"].ID:
+ return _BurnToAddressMintTokenPool.ParseOwnershipTransferRequested(log)
+ case _BurnToAddressMintTokenPool.abi.Events["OwnershipTransferred"].ID:
+ return _BurnToAddressMintTokenPool.ParseOwnershipTransferred(log)
+ case _BurnToAddressMintTokenPool.abi.Events["RateLimitAdminSet"].ID:
+ return _BurnToAddressMintTokenPool.ParseRateLimitAdminSet(log)
+ case _BurnToAddressMintTokenPool.abi.Events["Released"].ID:
+ return _BurnToAddressMintTokenPool.ParseReleased(log)
+ case _BurnToAddressMintTokenPool.abi.Events["RemotePoolAdded"].ID:
+ return _BurnToAddressMintTokenPool.ParseRemotePoolAdded(log)
+ case _BurnToAddressMintTokenPool.abi.Events["RemotePoolRemoved"].ID:
+ return _BurnToAddressMintTokenPool.ParseRemotePoolRemoved(log)
+ case _BurnToAddressMintTokenPool.abi.Events["RouterUpdated"].ID:
+ return _BurnToAddressMintTokenPool.ParseRouterUpdated(log)
+ case _BurnToAddressMintTokenPool.abi.Events["TokensConsumed"].ID:
+ return _BurnToAddressMintTokenPool.ParseTokensConsumed(log)
+
+ default:
+ return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0])
+ }
+}
+
+func (BurnToAddressMintTokenPoolAllowListAdd) Topic() common.Hash {
+ return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8")
+}
+
+func (BurnToAddressMintTokenPoolAllowListRemove) Topic() common.Hash {
+ return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566")
+}
+
+func (BurnToAddressMintTokenPoolBurned) Topic() common.Hash {
+ return common.HexToHash("0x696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7")
+}
+
+func (BurnToAddressMintTokenPoolChainAdded) Topic() common.Hash {
+ return common.HexToHash("0x8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2")
+}
+
+func (BurnToAddressMintTokenPoolChainConfigured) Topic() common.Hash {
+ return common.HexToHash("0x0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b")
+}
+
+func (BurnToAddressMintTokenPoolChainRemoved) Topic() common.Hash {
+ return common.HexToHash("0x5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916")
+}
+
+func (BurnToAddressMintTokenPoolConfigChanged) Topic() common.Hash {
+ return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19")
+}
+
+func (BurnToAddressMintTokenPoolLocked) Topic() common.Hash {
+ return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008")
+}
+
+func (BurnToAddressMintTokenPoolMinted) Topic() common.Hash {
+ return common.HexToHash("0x9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0")
+}
+
+func (BurnToAddressMintTokenPoolOwnershipTransferRequested) Topic() common.Hash {
+ return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278")
+}
+
+func (BurnToAddressMintTokenPoolOwnershipTransferred) Topic() common.Hash {
+ return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0")
+}
+
+func (BurnToAddressMintTokenPoolRateLimitAdminSet) Topic() common.Hash {
+ return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174")
+}
+
+func (BurnToAddressMintTokenPoolReleased) Topic() common.Hash {
+ return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52")
+}
+
+func (BurnToAddressMintTokenPoolRemotePoolAdded) Topic() common.Hash {
+ return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea")
+}
+
+func (BurnToAddressMintTokenPoolRemotePoolRemoved) Topic() common.Hash {
+ return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76")
+}
+
+func (BurnToAddressMintTokenPoolRouterUpdated) Topic() common.Hash {
+ return common.HexToHash("0x02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684")
+}
+
+func (BurnToAddressMintTokenPoolTokensConsumed) Topic() common.Hash {
+ return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a")
+}
+
+func (_BurnToAddressMintTokenPool *BurnToAddressMintTokenPool) Address() common.Address {
+ return _BurnToAddressMintTokenPool.address
+}
+
+type BurnToAddressMintTokenPoolInterface interface {
+ GetAllowList(opts *bind.CallOpts) ([]common.Address, error)
+
+ GetAllowListEnabled(opts *bind.CallOpts) (bool, error)
+
+ GetBurnAddress(opts *bind.CallOpts) (common.Address, error)
+
+ GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error)
+
+ GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error)
+
+ GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error)
+
+ GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error)
+
+ GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error)
+
+ GetRmnProxy(opts *bind.CallOpts) (common.Address, error)
+
+ GetRouter(opts *bind.CallOpts) (common.Address, error)
+
+ GetSupportedChains(opts *bind.CallOpts) ([]uint64, error)
+
+ GetToken(opts *bind.CallOpts) (common.Address, error)
+
+ GetTokenDecimals(opts *bind.CallOpts) (uint8, error)
+
+ IBurnAddress(opts *bind.CallOpts) (common.Address, error)
+
+ IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error)
+
+ IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error)
+
+ IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error)
+
+ Owner(opts *bind.CallOpts) (common.Address, error)
+
+ SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error)
+
+ TypeAndVersion(opts *bind.CallOpts) (string, error)
+
+ AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error)
+
+ AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error)
+
+ ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error)
+
+ ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error)
+
+ LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error)
+
+ ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error)
+
+ RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error)
+
+ SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error)
+
+ SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error)
+
+ SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error)
+
+ SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error)
+
+ TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error)
+
+ FilterAllowListAdd(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolAllowListAddIterator, error)
+
+ WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolAllowListAdd) (event.Subscription, error)
+
+ ParseAllowListAdd(log types.Log) (*BurnToAddressMintTokenPoolAllowListAdd, error)
+
+ FilterAllowListRemove(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolAllowListRemoveIterator, error)
+
+ WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolAllowListRemove) (event.Subscription, error)
+
+ ParseAllowListRemove(log types.Log) (*BurnToAddressMintTokenPoolAllowListRemove, error)
+
+ FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*BurnToAddressMintTokenPoolBurnedIterator, error)
+
+ WatchBurned(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolBurned, sender []common.Address) (event.Subscription, error)
+
+ ParseBurned(log types.Log) (*BurnToAddressMintTokenPoolBurned, error)
+
+ FilterChainAdded(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainAddedIterator, error)
+
+ WatchChainAdded(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainAdded) (event.Subscription, error)
+
+ ParseChainAdded(log types.Log) (*BurnToAddressMintTokenPoolChainAdded, error)
+
+ FilterChainConfigured(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainConfiguredIterator, error)
+
+ WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainConfigured) (event.Subscription, error)
+
+ ParseChainConfigured(log types.Log) (*BurnToAddressMintTokenPoolChainConfigured, error)
+
+ FilterChainRemoved(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolChainRemovedIterator, error)
+
+ WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolChainRemoved) (event.Subscription, error)
+
+ ParseChainRemoved(log types.Log) (*BurnToAddressMintTokenPoolChainRemoved, error)
+
+ FilterConfigChanged(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolConfigChangedIterator, error)
+
+ WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolConfigChanged) (event.Subscription, error)
+
+ ParseConfigChanged(log types.Log) (*BurnToAddressMintTokenPoolConfigChanged, error)
+
+ FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*BurnToAddressMintTokenPoolLockedIterator, error)
+
+ WatchLocked(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolLocked, sender []common.Address) (event.Subscription, error)
+
+ ParseLocked(log types.Log) (*BurnToAddressMintTokenPoolLocked, error)
+
+ FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnToAddressMintTokenPoolMintedIterator, error)
+
+ WatchMinted(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error)
+
+ ParseMinted(log types.Log) (*BurnToAddressMintTokenPoolMinted, error)
+
+ FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnToAddressMintTokenPoolOwnershipTransferRequestedIterator, error)
+
+ WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error)
+
+ ParseOwnershipTransferRequested(log types.Log) (*BurnToAddressMintTokenPoolOwnershipTransferRequested, error)
+
+ FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnToAddressMintTokenPoolOwnershipTransferredIterator, error)
+
+ WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error)
+
+ ParseOwnershipTransferred(log types.Log) (*BurnToAddressMintTokenPoolOwnershipTransferred, error)
+
+ FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolRateLimitAdminSetIterator, error)
+
+ WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRateLimitAdminSet) (event.Subscription, error)
+
+ ParseRateLimitAdminSet(log types.Log) (*BurnToAddressMintTokenPoolRateLimitAdminSet, error)
+
+ FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnToAddressMintTokenPoolReleasedIterator, error)
+
+ WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error)
+
+ ParseReleased(log types.Log) (*BurnToAddressMintTokenPoolReleased, error)
+
+ FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnToAddressMintTokenPoolRemotePoolAddedIterator, error)
+
+ WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error)
+
+ ParseRemotePoolAdded(log types.Log) (*BurnToAddressMintTokenPoolRemotePoolAdded, error)
+
+ FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnToAddressMintTokenPoolRemotePoolRemovedIterator, error)
+
+ WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error)
+
+ ParseRemotePoolRemoved(log types.Log) (*BurnToAddressMintTokenPoolRemotePoolRemoved, error)
+
+ FilterRouterUpdated(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolRouterUpdatedIterator, error)
+
+ WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolRouterUpdated) (event.Subscription, error)
+
+ ParseRouterUpdated(log types.Log) (*BurnToAddressMintTokenPoolRouterUpdated, error)
+
+ FilterTokensConsumed(opts *bind.FilterOpts) (*BurnToAddressMintTokenPoolTokensConsumedIterator, error)
+
+ WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *BurnToAddressMintTokenPoolTokensConsumed) (event.Subscription, error)
+
+ ParseTokensConsumed(log types.Log) (*BurnToAddressMintTokenPoolTokensConsumed, 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
index a8ee1906951..a9e3eb0f4de 100644
--- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go
+++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go
@@ -159,7 +159,7 @@ type KeystoneFeedsPermissionHandlerPermission struct {
var FeeQuoterMetaData = &bind.MetaData{
ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"staticConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.StaticConfig\",\"components\":[{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"linkToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"name\":\"priceUpdaters\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"feeTokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feedConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]},{\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}]},{\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"FEE_BASE_DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAuthorizedCallerUpdates\",\"inputs\":[{\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\",\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"components\":[{\"name\":\"addedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"removedCallers\",\"type\":\"address[]\",\"internalType\":\"address[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyDestChainConfigUpdates\",\"inputs\":[{\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyFeeTokensUpdates\",\"inputs\":[{\"name\":\"feeTokensToRemove\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"feeTokensToAdd\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"inputs\":[{\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyTokenTransferFeeConfigUpdates\",\"inputs\":[{\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}]},{\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"convertTokenAmount\",\"inputs\":[{\"name\":\"fromToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fromTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"toToken\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllAuthorizedCallers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getDestinationChainGasPrice\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structInternal.TimestampedPackedUint224\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFeeTokens\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPremiumMultiplierWeiPerEth\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getStaticConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.StaticConfig\",\"components\":[{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"linkToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenAndGasPrices\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"tokenPrice\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"gasPriceValue\",\"type\":\"uint224\",\"internalType\":\"uint224\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPrice\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structInternal.TimestampedPackedUint224\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPriceFeedConfig\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenPrices\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"components\":[{\"name\":\"value\",\"type\":\"uint224\",\"internalType\":\"uint224\"},{\"name\":\"timestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenTransferFeeConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatedFee\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.EVM2AnyMessage\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"tokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getValidatedTokenPrice\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint224\",\"internalType\":\"uint224\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"onReport\",\"inputs\":[{\"name\":\"metadata\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"report\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"processMessageArgs\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"feeToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feeTokenAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"extraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"components\":[{\"name\":\"sourcePoolAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"destExecData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"msgFeeJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"convertedExtraArgs\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setReportPermissions\",\"inputs\":[{\"name\":\"permissions\",\"type\":\"tuple[]\",\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"components\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"isAllowed\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updatePrices\",\"inputs\":[{\"name\":\"priceUpdates\",\"type\":\"tuple\",\"internalType\":\"structInternal.PriceUpdates\",\"components\":[{\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"usdPerToken\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]},{\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structInternal.GasPriceUpdate[]\",\"components\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"usdPerUnitGas\",\"type\":\"uint224\",\"internalType\":\"uint224\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateTokenPriceFeeds\",\"inputs\":[{\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\",\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"components\":[{\"name\":\"sourceToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"feedConfig\",\"type\":\"tuple\",\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AuthorizedCallerAdded\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AuthorizedCallerRemoved\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DestChainAdded\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DestChainConfigUpdated\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"destChainConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"maxDataBytes\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerPayloadByteBase\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteHigh\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"destGasPerPayloadByteThreshold\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"},{\"name\":\"enforceOutOfOrder\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeTokenAdded\",\"inputs\":[{\"name\":\"feeToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FeeTokenRemoved\",\"inputs\":[{\"name\":\"feeToken\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PriceFeedPerTokenUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"priceFeedConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"components\":[{\"name\":\"dataFeedAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ReportPermissionSet\",\"inputs\":[{\"name\":\"reportId\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"permission\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"components\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"isAllowed\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeeConfigDeleted\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokenTransferFeeConfigUpdated\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"components\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"deciBps\",\"type\":\"uint16\",\"internalType\":\"uint16\"},{\"name\":\"destGasOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UsdPerTokenUpdated\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UsdPerUnitGasUpdated\",\"inputs\":[{\"name\":\"destChain\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DataFeedValueOutOfUint224Range\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DestinationChainNotEnabled\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FeeTokenNotSupported\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"InvalidChainFamilySelector\",\"inputs\":[{\"name\":\"chainFamilySelector\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}]},{\"type\":\"error\",\"name\":\"InvalidDestBytesOverhead\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"destBytesOverhead\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]},{\"type\":\"error\",\"name\":\"InvalidDestChainConfig\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidEVMAddress\",\"inputs\":[{\"name\":\"encodedAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidExtraArgsData\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidExtraArgsTag\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidFeeRange\",\"inputs\":[{\"name\":\"minFeeUSDCents\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidSVMAddress\",\"inputs\":[{\"name\":\"SVMAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidStaticConfig\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTokenReceiver\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageComputeUnitLimitTooHigh\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageFeeTooHigh\",\"inputs\":[{\"name\":\"msgFeeJuels\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"MessageGasLimitTooHigh\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MessageTooLarge\",\"inputs\":[{\"name\":\"maxSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ReportForwarderUnauthorized\",\"inputs\":[{\"name\":\"forwarder\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"workflowName\",\"type\":\"bytes10\",\"internalType\":\"bytes10\"},{\"name\":\"reportName\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}]},{\"type\":\"error\",\"name\":\"SourceTokenDataTooLarge\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"StaleGasPrice\",\"inputs\":[{\"name\":\"destChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"threshold\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timePassed\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"TokenNotSupported\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnauthorizedCaller\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"UnsupportedNumberOfTokens\",\"inputs\":[{\"name\":\"numberOfTokens\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]",
- Bin: "0x60e060405234611029576170618038038061001981611295565b9283398101908082036101208112611029576060136110295761003a611257565b81516001600160601b038116810361102957815261005a602083016112ba565b906020810191825261006e604084016112ce565b6040820190815260608401516001600160401b03811161102957856100949186016112f6565b60808501519094906001600160401b03811161102957866100b69183016112f6565b60a08201519096906001600160401b0381116110295782019080601f830112156110295781516100ed6100e8826112df565b611295565b9260208085848152019260071b8201019083821161102957602001915b8183106111e25750505060c08301516001600160401b0381116110295783019781601f8a011215611029578851986101446100e88b6112df565b996020808c838152019160051b830101918483116110295760208101915b838310611080575050505060e08401516001600160401b0381116110295784019382601f8601121561102957845161019c6100e8826112df565b9560208088848152019260061b8201019085821161102957602001915b81831061104457505050610100810151906001600160401b038211611029570182601f82011215611029578051906101f36100e8836112df565b93602061028081878681520194028301019181831161102957602001925b828410610e6757505050503315610e5657600180546001600160a01b031916331790556020986102408a611295565b97600089526000368137610252611276565b998a52888b8b015260005b89518110156102c4576001906001600160a01b0361027b828d61138f565b51168d6102878261157b565b610294575b50500161025d565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1388d61028c565b508a985089519660005b885181101561033f576001600160a01b036102e9828b61138f565b511690811561032e577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef8c83610320600195611503565b50604051908152a1016102ce565b6342bcdf7f60e11b60005260046000fd5b5081518a985089906001600160a01b0316158015610e44575b8015610e35575b610e245791516001600160a01b031660a05290516001600160601b03166080525163ffffffff1660c05261039286611295565b9360008552600036813760005b855181101561040e576001906103c76001600160a01b036103c0838a61138f565b5116611410565b6103d2575b0161039f565b818060a01b036103e2828961138f565b51167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a26103cc565b508694508560005b84518110156104855760019061043e6001600160a01b03610437838961138f565b5116611542565b610449575b01610416565b818060a01b03610459828861138f565b51167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2610443565b508593508460005b835181101561054757806104a36001928661138f565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf606089858060a01b038451169301518360005260078b5260406000209060ff878060a01b038251169283898060a01b03198254161781558d8301908151604082549501948460a81b8651151560a81b16918560a01b9060a01b169061ffff60a01b19161717905560405193845251168c8301525115156040820152a20161048d565b5091509160005b8251811015610abc57610561818461138f565b51856001600160401b03610575848761138f565b5151169101519080158015610aa9575b8015610a8b575b610a7757600081815260098852604090205460019392919060081b6001600160e01b03191661092f57807f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806106f5868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a25b60005260098752826040600020825115158382549162ffff008c83015160081b169066ffffffff000000604084015160181b166affffffff00000000000000606085015160381b16926effffffff0000000000000000000000608086015160581b169260ff60781b60a087015160781b169460ff60801b60c088015160801b169161ffff60881b60e089015160881b169063ffffffff60981b6101008a015160981b169361ffff60b81b6101208b015160b81b169661ffff60c81b6101408c015160c81b169963ffffffff60d81b6101608d015160081c169b61018060ff60f81b910151151560f81b169c8f8060f81b039a63ffffffff60d81b199961ffff60c81b199861ffff60b81b199763ffffffff60981b199661ffff60881b199560ff60801b199460ff60781b19936effffffff0000000000000000000000199260ff6affffffff000000000000001992169066ffffffffffffff19161716171617161716171617161716171617161716179063ffffffff60d81b1617178155019061ffff6101a0820151169082549165ffffffff00006101c083015160101b169269ffffffff0000000000006101e084015160301b166a01000000000000000000008860901b0361020085015160501b169263ffffffff60901b61022086015160901b169461024063ffffffff60b01b91015160b01b169563ffffffff60b01b199363ffffffff60901b19926a01000000000000000000008c60901b0319918c8060501b03191617161716171617171790550161054e565b807f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e360405180610a6f868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a26106f9565b63c35aa79d60e01b60005260045260246000fd5b5063ffffffff6101e08301511663ffffffff6060840151161061058c565b5063ffffffff6101e08301511615610585565b84828560005b8151811015610b42576001906001600160a01b03610ae0828561138f565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d86848060401b0381610b16868961138f565b510151168360005260088252604060002081878060401b0319825416179055604051908152a201610ac2565b83600184610b4f83611295565b9060008252600092610e1f575b909282935b8251851015610d5e57610b74858461138f565b5180516001600160401b0316939083019190855b83518051821015610d4d57610b9e82879261138f565b51015184516001600160a01b0390610bb790849061138f565b5151169063ffffffff815116908781019163ffffffff8351169081811015610d385750506080810163ffffffff815116898110610d21575090899291838c52600a8a5260408c20600160a01b6001900386168d528a5260408c2092825163ffffffff169380549180518d1b67ffffffff0000000016916040860192835160401b69ffff000000000000000016966060810195865160501b6dffffffff00000000000000000000169063ffffffff60701b895160701b169260a001998b60ff60901b8c51151560901b169560ff60901b199363ffffffff60701b19926dffffffff000000000000000000001991600160501b60019003191617161716171617171790556040519586525163ffffffff168c8601525161ffff1660408501525163ffffffff1660608401525163ffffffff16608083015251151560a082015260c07f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b591a3600101610b88565b6312766e0160e11b8c52600485905260245260448bfd5b6305a7b3d160e11b8c5260045260245260448afd5b505060019096019593509050610b61565b9150825b8251811015610de0576001906001600160401b03610d80828661138f565b515116828060a01b0384610d94848861138f565b5101511690808752600a855260408720848060a01b038316885285528660408120557f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b8780a301610d62565b604051615a519081611610823960805181818161044201526129ff015260a05181818161047801526129b0015260c05181818161049f01526136d60152f35b610b5c565b63d794ef9560e01b60005260046000fd5b5063ffffffff8251161561035f565b5080516001600160601b031615610358565b639b15e16f60e01b60005260046000fd5b838203610280811261102957610260610e7e611276565b91610e888761136c565b8352601f190112611029576040519161026083016001600160401b0381118482101761102e57604052610ebd6020870161135f565b8352610ecb60408701611380565b6020840152610edc606087016112ce565b6040840152610eed608087016112ce565b6060840152610efe60a087016112ce565b6080840152610f0f60c08701611351565b60a0840152610f2060e08701611351565b60c0840152610f326101008701611380565b60e0840152610f4461012087016112ce565b610100840152610f576101408701611380565b610120840152610f6a6101608701611380565b610140840152610180860151916001600160e01b0319831683036110295783602093610160610280960152610fa26101a0890161135f565b610180820152610fb56101c08901611380565b6101a0820152610fc86101e089016112ce565b6101c0820152610fdb61020089016112ce565b6101e0820152610fee610220890161136c565b61020082015261100161024089016112ce565b61022082015261101461026089016112ce565b61024082015283820152815201930192610211565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60408387031261102957602060409161105b611276565b611064866112ba565b815261107183870161136c565b838201528152019201916101b9565b82516001600160401b0381116110295782016040818803601f190112611029576110a8611276565b906110b56020820161136c565b825260408101516001600160401b03811161102957602091010187601f820112156110295780516110e86100e8826112df565b91602060e08185858152019302820101908a821161102957602001915b8183106111245750505091816020938480940152815201920191610162565b828b0360e081126110295760c0611139611276565b91611143866112ba565b8352601f190112611029576040519160c08301916001600160401b0383118484101761102e5760e09360209360405261117d8488016112ce565b815261118b604088016112ce565b8482015261119b60608801611380565b60408201526111ac608088016112ce565b60608201526111bd60a088016112ce565b60808201526111ce60c0880161135f565b60a082015283820152815201920191611105565b828403608081126110295760606111f7611276565b91611201866112ba565b8352601f1901126110295760809160209161121a611257565b6112258488016112ba565b815261123360408801611351565b848201526112436060880161135f565b60408201528382015281520192019161010a565b60405190606082016001600160401b0381118382101761102e57604052565b60408051919082016001600160401b0381118382101761102e57604052565b6040519190601f01601f191682016001600160401b0381118382101761102e57604052565b51906001600160a01b038216820361102957565b519063ffffffff8216820361102957565b6001600160401b03811161102e5760051b60200190565b9080601f830112156110295781516113106100e8826112df565b9260208085848152019260051b82010192831161102957602001905b8282106113395750505090565b60208091611346846112ba565b81520191019061132c565b519060ff8216820361102957565b5190811515820361102957565b51906001600160401b038216820361102957565b519061ffff8216820361102957565b80518210156113a35760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156113a35760005260206000200190600090565b805480156113fa5760001901906113e882826113b9565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6000818152600c602052604090205480156114d15760001981018181116114bb57600b546000198101919082116114bb5781810361146a575b505050611456600b6113d1565b600052600c60205260006040812055600190565b6114a361147b61148c93600b6113b9565b90549060031b1c928392600b6113b9565b819391549060031b91821b91600019901b19161790565b9055600052600c602052604060002055388080611449565b634e487b7160e01b600052601160045260246000fd5b5050600090565b8054906801000000000000000082101561102e578161148c9160016114ff940181556113b9565b9055565b8060005260036020526040600020541560001461153c576115258160026114d8565b600254906000526003602052604060002055600190565b50600090565b80600052600c6020526040600020541560001461153c5761156481600b6114d8565b600b5490600052600c602052604060002055600190565b60008181526003602052604090205480156114d15760001981018181116114bb576002546000198101919082116114bb578082036115d5575b5050506115c160026113d1565b600052600360205260006040812055600190565b6115f76115e661148c9360026113b9565b90549060031b1c92839260026113b9565b905560005260036020526040600020553880806115b456fe6080604052600436101561001257600080fd5b60003560e01c806241e5be1461020657806301ffc9a714610201578063061877e3146101fc57806306285c69146101f7578063181f5a77146101f25780632451a627146101ed578063325c868e146101e85780633937306f146101e357806341ed29e7146101de578063430d138c146101d957806345ac924d146101d45780634ab35b0b146101cf578063514e8cff146101ca5780636def4ce7146101c5578063770e2dc4146101c057806379ba5097146101bb5780637afac322146101b6578063805f2132146101b157806382b49eb0146101ac57806387b8d879146101a75780638da5cb5b146101a257806391a2749a1461019d578063a69c64c014610198578063bf78e03f14610193578063cdc73d511461018e578063d02641a014610189578063d63d3af214610184578063d8694ccd1461017f578063f2fde38b1461017a578063fbe3f778146101755763ffdb4b371461017057600080fd5b612556565b612459565b61239d565b611f78565b611f5c565b611f13565b611e9c565b611df6565b611d3d565b611ca9565b611c82565b611a66565b6118e9565b61164e565b611515565b6113fd565b6111de565b61105f565b610e88565b610e50565b610d87565b610c5a565b6109ff565b610743565b610727565b6106a4565b6105fe565b610406565b6103be565b61029a565b61022e565b6001600160a01b0381160361021c57565b600080fd5b359061022c8261020b565b565b3461021c57606060031936011261021c5760206102656004356102508161020b565b602435604435916102608361020b565b6126d8565b604051908152f35b35907fffffffff000000000000000000000000000000000000000000000000000000008216820361021c57565b3461021c57602060031936011261021c576004357fffffffff000000000000000000000000000000000000000000000000000000008116810361021c577fffffffff00000000000000000000000000000000000000000000000000000000602091167f805f2132000000000000000000000000000000000000000000000000000000008114908115610394575b811561036a575b8115610340575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610335565b7f181f5a77000000000000000000000000000000000000000000000000000000008114915061032e565b7f9b645f410000000000000000000000000000000000000000000000000000000081149150610327565b3461021c57602060031936011261021c576001600160a01b036004356103e38161020b565b166000526008602052602067ffffffffffffffff60406000205416604051908152f35b3461021c57600060031936011261021c5761041f61270c565b50606060405161042e81610506565b63ffffffff6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016918281526001600160a01b0360406020830192827f00000000000000000000000000000000000000000000000000000000000000001684520191837f00000000000000000000000000000000000000000000000000000000000000001683526040519485525116602084015251166040820152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761052257604052565b6104d7565b60a0810190811067ffffffffffffffff82111761052257604052565b6040810190811067ffffffffffffffff82111761052257604052565b60c0810190811067ffffffffffffffff82111761052257604052565b90601f601f19910116810190811067ffffffffffffffff82111761052257604052565b6040519061022c60408361057b565b6040519061022c6102608361057b565b919082519283825260005b8481106105e9575050601f19601f8460006020809697860101520116010190565b806020809284010151828286010152016105c8565b3461021c57600060031936011261021c5761065d6040805190610621818361057b565b601382527f46656551756f74657220312e362e302d646576000000000000000000000000006020830152519182916020835260208301906105bd565b0390f35b602060408183019282815284518094520192019060005b8181106106855750505090565b82516001600160a01b0316845260209384019390920191600101610678565b3461021c57600060031936011261021c5760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b8181106107115761065d856107058187038261057b565b60405191829182610661565b82548452602090930192600192830192016106ee565b3461021c57600060031936011261021c57602060405160248152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c5780600401906040600319823603011261021c57610781613a0f565b61078b828061272b565b4263ffffffff1692915060005b8181106108fc575050602401906107af828461272b565b92905060005b8381106107be57005b806107dd6107d86001936107d2868a61272b565b906127ae565b61280e565b7fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e67ffffffffffffffff6108d86108ca60208501946108bc61082687516001600160e01b031690565b61084061083161059e565b6001600160e01b039092168252565b63ffffffff8c16602082015261087b610861845167ffffffffffffffff1690565b67ffffffffffffffff166000526005602052604060002090565b815160209092015160e01b7fffffffff00000000000000000000000000000000000000000000000000000000166001600160e01b0392909216919091179055565b5167ffffffffffffffff1690565b93516001600160e01b031690565b604080516001600160e01b039290921682524260208301529190931692a2016107b5565b806109156109106001936107d2898061272b565b6127d7565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036109ae6108ca60208501946109a161095d87516001600160e01b031690565b61096861083161059e565b63ffffffff8d16602082015261087b61098884516001600160a01b031690565b6001600160a01b03166000526006602052604060002090565b516001600160a01b031690565b604080516001600160e01b039290921682524260208301529190931692a201610798565b67ffffffffffffffff81116105225760051b60200190565b8015150361021c57565b359061022c826109ea565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590610a3c826109d2565b90610a4a604051928361057b565b828252602460a06020840194028201019036821161021c57602401925b818410610a7957610a7783612833565b005b60a08436031261021c5760405190610a9082610527565b8435610a9b8161020b565b825260208501357fffffffffffffffffffff000000000000000000000000000000000000000000008116810361021c5760208301526040850135907fffff0000000000000000000000000000000000000000000000000000000000008216820361021c5782602092604060a0950152610b1660608801610221565b6060820152610b27608088016109f4565b6080820152815201930192610a67565b6004359067ffffffffffffffff8216820361021c57565b6024359067ffffffffffffffff8216820361021c57565b359067ffffffffffffffff8216820361021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020838186019501011161021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020808501948460051b01011161021c57565b929091610bfa928452151560208401526080604084015260808301906105bd565b906060818303910152815180825260208201916020808360051b8301019401926000915b838310610c2d57505050505090565b9091929394602080610c4b83601f19866001960301875289516105bd565b97019301930191939290610c1e565b3461021c5760c060031936011261021c57610c73610b37565b60243590610c808261020b565b60443560643567ffffffffffffffff811161021c57610ca3903690600401610b7a565b60849391933567ffffffffffffffff811161021c57610cc6903690600401610ba8565b9160a4359567ffffffffffffffff871161021c573660238801121561021c5786600401359567ffffffffffffffff871161021c573660248860061b8a01011161021c5761065d986024610d1a9901966129a5565b9060409492945194859485610bd9565b602060408183019282815284518094520192019060005b818110610d4e5750505090565b9091926020604082610d7c600194885163ffffffff602080926001600160e01b038151168552015116910152565b019401929101610d41565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c57610db8903690600401610ba8565b610dc1816109d2565b91610dcf604051938461057b565b818352601f19610dde836109d2565b0160005b818110610e3957505060005b82811015610e2b57600190610e0f610e0a8260051b8501612cbc565b613682565b610e198287612991565b52610e248186612991565b5001610dee565b6040518061065d8682610d2a565b602090610e44612ca3565b82828801015201610de2565b3461021c57602060031936011261021c576020610e77600435610e728161020b565b613997565b6001600160e01b0360405191168152f35b3461021c57602060031936011261021c5767ffffffffffffffff610eaa610b37565b610eb2612ca3565b50166000526005602052604060002060405190610ece82610543565b546001600160e01b038116825260e01c6020820152604051809161065d82604081019263ffffffff602080926001600160e01b038151168552015116910152565b61022c9092919261024080610260830195610f2c84825115159052565b60208181015161ffff169085015260408181015163ffffffff169085015260608181015163ffffffff169085015260808181015163ffffffff169085015260a08181015160ff169085015260c08181015160ff169085015260e08181015161ffff16908501526101008181015163ffffffff16908501526101208181015161ffff16908501526101408181015161ffff1690850152610160818101517fffffffff000000000000000000000000000000000000000000000000000000001690850152610180818101511515908501526101a08181015161ffff16908501526101c08181015163ffffffff16908501526101e08181015163ffffffff16908501526102008181015167ffffffffffffffff16908501526102208181015163ffffffff1690850152015163ffffffff16910152565b3461021c57602060031936011261021c5761065d61112261111d611081610b37565b600061024061108e6105ad565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a0820152826101c0820152826101e08201528261020082015282610220820152015267ffffffffffffffff166000526009602052604060002090565b612ceb565b60405191829182610f0f565b359063ffffffff8216820361021c57565b359061ffff8216820361021c57565b81601f8201121561021c57803590611165826109d2565b92611173604051948561057b565b82845260208085019360061b8301019181831161021c57602001925b82841061119d575050505090565b60408483031261021c57602060409182516111b781610543565b6111c087610b65565b8152828701356111cf8161020b565b8382015281520193019261118f565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013561121a816109d2565b91611228604051938461057b565b8183526024602084019260051b8201019036821161021c5760248101925b828410611277576024358567ffffffffffffffff821161021c57611271610a7792369060040161114e565b90612e59565b833567ffffffffffffffff811161021c57820160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc823603011261021c57604051906112c382610543565b6112cf60248201610b65565b8252604481013567ffffffffffffffff811161021c57602491010136601f8201121561021c578035611300816109d2565b9161130e604051938461057b565b818352602060e081850193028201019036821161021c57602001915b8183106113495750505091816020938480940152815201930192611246565b82360360e0811261021c5760c0601f196040519261136684610543565b86356113718161020b565b8452011261021c5760e09160209160405161138b8161055f565b61139684880161112e565b81526113a46040880161112e565b848201526113b46060880161113f565b60408201526113c56080880161112e565b60608201526113d660a0880161112e565b608082015260c08701356113e9816109ea565b60a08201528382015281520192019161132a565b3461021c57600060031936011261021c576000546001600160a01b0381163303611484577fffffffffffffffffffffffff0000000000000000000000000000000000000000600154913382841617600155166000556001600160a01b033391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b9080601f8301121561021c5781356114c5816109d2565b926114d3604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106114fb5750505090565b60208091833561150a8161020b565b8152019101906114ee565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c576115469036906004016114ae565b60243567ffffffffffffffff811161021c576115669036906004016114ae565b9061156f613a53565b60005b81518110156115de578061159361158e6109a160019486612991565b615656565b61159e575b01611572565b6001600160a01b036115b36109a18386612991565b167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a2611598565b8260005b8151811015610a7757806116036115fe6109a160019486612991565b61566a565b61160e575b016115e2565b6001600160a01b036116236109a18386612991565b167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2611608565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c5761167f903690600401610b7a565b6024359167ffffffffffffffff831161021c576116d86116d06116b66116ac6116e0963690600401610b7a565b9490953691613108565b90604082015190605e604a84015160601c93015191929190565b919033613eb7565b81019061314f565b60005b8151811015610a775761172b61172661170d6116ff8486612991565b51516001600160a01b031690565b6001600160a01b03166000526007602052604060002090565b61320e565b61173f61173b6040830151151590565b1590565b6118a0579061178a6117576020600194015160ff1690565b61178461177860206117698689612991565b5101516001600160e01b031690565b6001600160e01b031690565b90613f89565b6117a560406117998487612991565b51015163ffffffff1690565b63ffffffff6117d06117c76117c06109886116ff888b612991565b5460e01c90565b63ffffffff1690565b91161061189a5761181e6117e960406117998588612991565b61180e6117f461059e565b6001600160e01b03851681529163ffffffff166020830152565b61087b6109886116ff8689612991565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036118546116ff8588612991565b6118906118666040611799888b612991565b60405193849316958390929163ffffffff6020916001600160e01b03604085019616845216910152565b0390a25b016116e3565b50611894565b6118e56118b06116ff8486612991565b7f06439c6b000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b6000fd5b3461021c57604060031936011261021c5761065d611971611908610b37565b67ffffffffffffffff6024359161191e8361020b565b600060a060405161192e8161055f565b828152826020820152826040820152826060820152826080820152015216600052600a6020526040600020906001600160a01b0316600052602052604060002090565b6119ed6119e4604051926119848461055f565b5463ffffffff8116845263ffffffff8160201c16602085015261ffff8160401c1660408501526119cb6119be8263ffffffff9060501c1690565b63ffffffff166060860152565b63ffffffff607082901c16608085015260901c60ff1690565b151560a0830152565b6040519182918291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b60ff81160361021c57565b359061022c82611a50565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611aa3826109d2565b90611ab1604051928361057b565b82825260246102806020840194028201019036821161021c57602401925b818410611adf57610a778361329e565b833603610280811261021c57610260601f1960405192611afe84610543565b611b0788610b65565b8452011261021c5761028091602091611b1e6105ad565b611b298489016109f4565b8152611b376040890161113f565b84820152611b476060890161112e565b6040820152611b586080890161112e565b6060820152611b6960a0890161112e565b6080820152611b7a60c08901611a5b565b60a0820152611b8b60e08901611a5b565b60c0820152611b9d610100890161113f565b60e0820152611baf610120890161112e565b610100820152611bc2610140890161113f565b610120820152611bd5610160890161113f565b610140820152611be8610180890161026d565b610160820152611bfb6101a089016109f4565b610180820152611c0e6101c0890161113f565b6101a0820152611c216101e0890161112e565b6101c0820152611c34610200890161112e565b6101e0820152611c476102208901610b65565b610200820152611c5a610240890161112e565b610220820152611c6d610260890161112e565b61024082015283820152815201930192611acf565b3461021c57600060031936011261021c5760206001600160a01b0360015416604051908152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c576040600319823603011261021c57604051611ce681610543565b816004013567ffffffffffffffff811161021c57611d0a90600436918501016114ae565b8152602482013567ffffffffffffffff811161021c57610a77926004611d3392369201016114ae565b6020820152613454565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611d7a826109d2565b90611d88604051928361057b565b8282526024602083019360061b8201019036821161021c57602401925b818410611db557610a77836135a6565b60408436031261021c5760206040918251611dcf81610543565b8635611dda8161020b565b8152611de7838801610b65565b83820152815201930192611da5565b3461021c57602060031936011261021c576001600160a01b03600435611e1b8161020b565b611e2361270c565b5016600052600760205261065d604060002060ff60405191611e4483610506565b546001600160a01b0381168352818160a01c16602084015260a81c16151560408201526040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b3461021c57600060031936011261021c57604051806020600b54918281520190600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99060005b818110611efd5761065d856107058187038261057b565b8254845260209093019260019283019201611ee6565b3461021c57602060031936011261021c576040611f35600435610e0a8161020b565b611f5a8251809263ffffffff602080926001600160e01b038151168552015116910152565bf35b3461021c57600060031936011261021c57602060405160128152f35b3461021c57604060031936011261021c57611f91610b37565b60243567ffffffffffffffff811161021c57806004019060a0600319823603011261021c57611fd761111d8467ffffffffffffffff166000526009602052604060002090565b606482019161200a61173b611feb85612cbc565b6001600160a01b03166000526001600b01602052604060002054151590565b61235c579081604485930195612020878561272b565b959050602461203c85612036608487018961379e565b906148cb565b93019061206b61204c838861379e565b9050858961206461205d8b8061379e565b3691613108565b9289614a74565b84612078610e7283612cbc565b98899461209661209061022085015163ffffffff1690565b82614b36565b9b6000808c156123225750506120fc61ffff856121219961210899989661213c9661212f966120f36120e36101c06120d76101a06121429f015161ffff1690565b97015163ffffffff1690565b916120ed8c612cbc565b9461272b565b96909516614c27565b98919897909894612cbc565b6001600160a01b03166000526008602052604060002090565b5467ffffffffffffffff1690565b67ffffffffffffffff1690565b9061268c565b9560009761ffff61215961014089015161ffff1690565b166122c7575b509461213c61212f61020061222d61065d9d6dffffffffffffffffffffffffffff6122256122459f9e9b6122206001600160e01b039f9b9c61223d9f6122209e63ffffffff6121b46122209f6121be9461379e565b92905016906137ef565b908b60a081016121e16121db6121d5835160ff1690565b60ff1690565b8561268c565b9360e08301916121f3835161ffff1690565b9061ffff82168311612255575b5050505060800151612220916117c79163ffffffff1661382d565b61382d565b6137ef565b91169061268c565b93015167ffffffffffffffff1690565b91169061269f565b6040519081529081906020820190565b6117c7949650612220959361ffff6122b66122a561221b9661229f61229861228f60809960ff6122896122bd9b5160ff1690565b166137fc565b965161ffff1690565b61ffff1690565b90613675565b61213c6121d560c08d015160ff1690565b91166137ef565b9593839550612200565b909594989750826122ed8b989495986dffffffffffffffffffffffffffff9060701c1690565b6dffffffffffffffffffffffffffff1691612308848961379e565b90506123149388614e49565b96979394389693929661215f565b969593509650505061213c61212f6121216121086123566123516117c761024061214299015163ffffffff1690565b612645565b94612cbc565b6118e561236884612cbc565b7f2502348c000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b3461021c57602060031936011261021c576001600160a01b036004356123c28161020b565b6123ca613a53565b1633811461242f57807fffffffffffffffffffffffff000000000000000000000000000000000000000060005416176000556001600160a01b03600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590612496826109d2565b906124a4604051928361057b565b8282526024602083019360071b8201019036821161021c57602401925b8184106124d157610a7783613847565b8336036080811261021c576060601f19604051926124ee84610543565b87356124f98161020b565b8452011261021c5760809160209160405161251381610506565b838801356125208161020b565b8152604088013561253081611a50565b848201526060880135612542816109ea565b6040820152838201528152019301926124c1565b3461021c57604060031936011261021c576004356125738161020b565b61257b610b4e565b9067ffffffffffffffff82169182600052600960205260ff60406000205416156125e8576125ab6125cc92613997565b92600052600960205263ffffffff60016040600020015460901c1690614b36565b604080516001600160e01b039384168152919092166020820152f35b827f99ac52f20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90662386f26fc10000820291808304662386f26fc10000149015171561266757565b612616565b90655af3107a4000820291808304655af3107a4000149015171561266757565b8181029291811591840414171561266757565b81156126a9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6127026126fc61270994936001600160e01b036126f58195613997565b169061268c565b92613997565b169061269f565b90565b6040519061271982610506565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c57602001918160061b3603831361021c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156127be5760061b0190565b61277f565b35906001600160e01b038216820361021c57565b60408136031261021c576128066020604051926127f384610543565b80356127fe8161020b565b8452016127c3565b602082015290565b60408136031261021c5761280660206040519261282a84610543565b6127fe81610b65565b9061283c613a53565b60005b825181101561298c578061285560019285612991565b517f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a360a06001600160a01b038351169260608101936001600160a01b0380865116957fffff0000000000000000000000000000000000000000000000000000000000006128f360208601947fffffffffffffffffffff00000000000000000000000000000000000000000000865116604088019a848c511692614eee565b977fffffffffffffffffffff00000000000000000000000000000000000000000000608087019561295f875115158c600052600460205260406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b8560405198511688525116602087015251166040850152511660608301525115156080820152a20161283f565b509050565b80518210156127be5760209160051b010190565b9895979692949391907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0382166001600160a01b03821614600014612c93575050935b6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016808611612c62575090612a35918715158a613a91565b979096612a82612a598367ffffffffffffffff166000526009602052604060002090565b5460081b7fffffffff000000000000000000000000000000000000000000000000000000001690565b90612a8c81613cda565b9760005b828110612aa4575050505050505093929190565b612ab7612ab28284896127ae565b612cbc565b8388612ad1612ac7858484613d23565b604081019061379e565b905060208111612be7575b508392612b0b612b0561205d612afb600198612b4697612b4197613d23565b602081019061379e565b8961541f565b612b298967ffffffffffffffff16600052600a602052604060002090565b906001600160a01b0316600052602052604060002090565b613244565b60a081015115612bab57612b8f612b676060612b8193015163ffffffff1690565b6040805163ffffffff909216602083015290928391820190565b03601f19810183528261057b565b612b99828d612991565b52612ba4818c612991565b5001612a90565b50612b81612b8f612be284612bd48a67ffffffffffffffff166000526009602052604060002090565b015460101c63ffffffff1690565b612b67565b915050612c1f6117c7612c1284612b298b67ffffffffffffffff16600052600a602052604060002090565b5460701c63ffffffff1690565b10612c2c57838838612adc565b7f36f536ca000000000000000000000000000000000000000000000000000000006000526001600160a01b031660045260246000fd5b857f6a92a4830000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b91612c9d926126d8565b936129f0565b60405190612cb082610543565b60006020838281520152565b356127098161020b565b90604051612cd381610543565b91546001600160e01b038116835260e01c6020830152565b9061022c612e4b6001612cfc6105ad565b94612dea612de08254612d18612d128260ff1690565b15158a52565b61ffff600882901c1660208a015263ffffffff601882901c1660408a015263ffffffff603882901c1660608a015263ffffffff605882901c1660808a015260ff607882901c1660a08a015260ff608082901c1660c08a015261ffff608882901c1660e08a015263ffffffff609882901c166101008a015261ffff60b882901c166101208a015261ffff60c882901c166101408a01527fffffffff00000000000000000000000000000000000000000000000000000000600882901b166101608a015260f81c90565b1515610180880152565b015461ffff81166101a086015263ffffffff601082901c166101c086015263ffffffff603082901c166101e086015267ffffffffffffffff605082901c1661020086015263ffffffff609082901c1661022086015260b01c63ffffffff1690565b63ffffffff16610240840152565b90612e62613a53565b6000915b805183101561305457612e798382612991565b5190612e8d825167ffffffffffffffff1690565b946020600093019367ffffffffffffffff8716935b8551805182101561303f57612eb982602092612991565b510151612eca6116ff838951612991565b8151602083015163ffffffff908116911681811015613006575050608082015163ffffffff1660208110612fc5575090867f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b56001600160a01b0384612f54858f60019998612b29612f4f9267ffffffffffffffff16600052600a602052604060002090565b613d63565b612fbc60405192839216958291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b0390a301612ea2565b7f24ecdc02000000000000000000000000000000000000000000000000000000006000526001600160a01b0390911660045263ffffffff1660245260446000fd5b7f0b4f67a20000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b50509550925092600191500191929092612e66565b50905060005b8151811015613104578061308261307360019385612991565b515167ffffffffffffffff1690565b67ffffffffffffffff6001600160a01b036130b160206130a28689612991565b5101516001600160a01b031690565b60006130d582612b298767ffffffffffffffff16600052600a602052604060002090565b551691167f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b600080a30161305a565b5050565b92919267ffffffffffffffff82116105225760405191613132601f8201601f19166020018461057b565b82948184528183011161021c578281602093846000960137010152565b60208183031261021c5780359067ffffffffffffffff821161021c570181601f8201121561021c57803590613183826109d2565b92613191604051948561057b565b8284526020606081860194028301019181831161021c57602001925b8284106131bb575050505090565b60608483031261021c5760206060916040516131d681610506565b86356131e18161020b565b81526131ee8388016127c3565b838201526131fe6040880161112e565b60408201528152019301926131ad565b9060405161321b81610506565b604060ff8294546001600160a01b0381168452818160a01c16602085015260a81c161515910152565b9061022c6040516132548161055f565b925463ffffffff8082168552602082811c821690860152604082811c61ffff1690860152605082901c81166060860152607082901c16608085015260901c60ff16151560a0840152565b906132a7613a53565b60005b825181101561298c576132bd8184612991565b5160206132cd6130738487612991565b9101519067ffffffffffffffff811680158015613435575b8015613407575b6133cf57916133958260019594613345613320612a5961339a9767ffffffffffffffff166000526009602052604060002090565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b6133a0577f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806133788782610f0f565b0390a267ffffffffffffffff166000526009602052604060002090565b614096565b016132aa565b7f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e3604051806133788782610f0f565b7fc35aa79d0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff821660045260246000fd5b506101e083015163ffffffff1663ffffffff61342d6117c7606087015163ffffffff1690565b9116116132ec565b5063ffffffff61344d6101e085015163ffffffff1690565b16156132e5565b61345c613a53565b60208101519160005b83518110156134e9578061347e6109a160019387612991565b6134a061349b6001600160a01b0383165b6001600160a01b031690565b6159b9565b6134ac575b5001613465565b6040516001600160a01b039190911681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758090602090a1386134a5565b5091505160005b8151811015613104576135066109a18284612991565b906001600160a01b0382161561357c577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef6135738361355861355361348f6001976001600160a01b031690565b615940565b506040516001600160a01b0390911681529081906020820190565b0390a1016134f0565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b6135ae613a53565b60005b815181101561310457806001600160a01b036135cf60019385612991565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d61366c67ffffffffffffffff602061360b8689612991565b51015116836000526008602052604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519182918291909167ffffffffffffffff6020820193169052565b0390a2016135b1565b9190820391821161266757565b61368a612ca3565b506136b06136ab826001600160a01b03166000526006602052604060002090565b612cc6565b60208101916136cf6136c96117c7855163ffffffff1690565b42613675565b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016116137775761172661371b916001600160a01b03166000526007602052604060002090565b61372b61173b6040830151151590565b801561377d575b6137775761373f90614764565b9163ffffffff6137676117c761375c602087015163ffffffff1690565b935163ffffffff1690565b911610613772575090565b905090565b50905090565b506001600160a01b0361379782516001600160a01b031690565b1615613732565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c5760200191813603831361021c57565b9190820180921161266757565b9061ffff8091169116029061ffff821691820361266757565b63ffffffff60209116019063ffffffff821161266757565b9063ffffffff8091169116019063ffffffff821161266757565b90613850613a53565b60005b825181101561298c578061386960019285612991565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf61398e60206001600160a01b0384511693015183600052600760205260406000206138ee6001600160a01b0383511682906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b602082015181547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000075ff0000000000000000000000000000000000000000006040870151151560a81b169360a01b169116171790556040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b0390a201613853565b6139a081613682565b9063ffffffff6020830151161580156139fd575b6139c65750516001600160e01b031690565b6001600160a01b03907f06439c6b000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b506001600160e01b03825116156139b4565b33600052600360205260406000205415613a2557565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6001600160a01b03600154163303613a6757565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b61111d613ab791959493929567ffffffffffffffff166000526009602052604060002090565b936101608501947f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613b2a88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613ca6577f1e10bdc4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613b9c88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613c1d576118e5613bcf87517fffffffff000000000000000000000000000000000000000000000000000000001690565b7f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff0000000000000000000000000000000000000000000000000000000016600452602490565b60609192939495508063ffffffff613c4c610180613c4486613c5596015163ffffffff1690565b930151151590565b911686866152ba565b015181613c9d575b50613c7357613c6d913691613108565b90600190565b7f5bed51920000000000000000000000000000000000000000000000000000000060005260046000fd5b90501538613c5d565b6101e00151939450613ccb93919291613cc5915063ffffffff166117c7565b9161503b565b906127096020613c448461515c565b90613ce4826109d2565b613cf1604051918261057b565b828152601f19613d0182946109d2565b019060005b828110613d1257505050565b806060602080938501015201613d06565b91908110156127be5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618136030182121561021c570190565b815181546020808501516040808701517fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090941663ffffffff958616179190921b67ffffffff00000000161791901b69ffff000000000000000016178255606083015161022c93613e739260a092613e15911685547fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff1660509190911b6dffffffff0000000000000000000016178555565b613e6c613e29608083015163ffffffff1690565b85547fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff1660709190911b71ffffffff000000000000000000000000000016178555565b0151151590565b81547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1690151560901b72ff00000000000000000000000000000000000016179055565b91929092613ec782828686614eee565b600052600460205260ff6040600020541615613ee35750505050565b6040517f097e17ff0000000000000000000000000000000000000000000000000000000081526001600160a01b0393841660048201529390921660248401527fffffffffffffffffffff0000000000000000000000000000000000000000000090911660448301527fffff000000000000000000000000000000000000000000000000000000000000166064820152608490fd5b0390fd5b604d811161266757600a0a90565b60ff1660120160ff81116126675760ff16906024821115614024577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820191821161266757613fda613fe092613f7b565b9061269f565b6001600160e01b038111613ffa576001600160e01b031690565b7f10cb51d10000000000000000000000000000000000000000000000000000000060005260046000fd5b9060240390602482116126675761213c61403d92613f7b565b613fe0565b9060ff80911691160160ff81116126675760ff16906024821115614024577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc820191821161266757613fda613fe092613f7b565b906146b0610240600161022c946140e16140b08651151590565b829060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6141276140f3602087015161ffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1660089190911b62ffff0016178255565b61417361413b604087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffff1660189190911b66ffffffff00000016178255565b6141c3614187606087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffff1660389190911b6affffffff0000000000000016178255565b6142176141d7608087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff1660589190911b6effffffff000000000000000000000016178255565b61426961422860a087015160ff1690565b82547fffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffff1660789190911b6fff00000000000000000000000000000016178255565b6142bc61427a60c087015160ff1690565b82547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff1660809190911b70ff0000000000000000000000000000000016178255565b6143126142ce60e087015161ffff1690565b82547fffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffffff1660889190911b72ffff000000000000000000000000000000000016178255565b61436f61432761010087015163ffffffff1690565b82547fffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffff1660989190911b76ffffffff0000000000000000000000000000000000000016178255565b6143cc61438261012087015161ffff1690565b82547fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff1660b89190911b78ffff000000000000000000000000000000000000000000000016178255565b61442b6143df61014087015161ffff1690565b82547fffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff1660c89190911b7affff0000000000000000000000000000000000000000000000000016178255565b6144ac61445c6101608701517fffffffff000000000000000000000000000000000000000000000000000000001690565b82547fff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff1660089190911c7effffffff00000000000000000000000000000000000000000000000000000016178255565b61450d6144bd610180870151151590565b82547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690151560f81b7fff0000000000000000000000000000000000000000000000000000000000000016178255565b01926145516145226101a083015161ffff1690565b859061ffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000825416179055565b61459d6145666101c083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff1660109190911b65ffffffff000016178555565b6145ed6145b26101e083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1660309190911b69ffffffff00000000000016178555565b61464961460661020083015167ffffffffffffffff1690565b85547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178555565b6146a561465e61022083015163ffffffff1690565b85547fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff1660909190911b75ffffffff00000000000000000000000000000000000016178555565b015163ffffffff1690565b7fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff79ffffffff0000000000000000000000000000000000000000000083549260b01b169116179055565b519069ffffffffffffffffffff8216820361021c57565b908160a091031261021c57614725816146fa565b916020820151916040810151916127096080606084015193016146fa565b6040513d6000823e3d90fd5b9081602091031261021c575161270981611a50565b61476c612ca3565b5061478461348f61348f83516001600160a01b031690565b90604051907ffeaf968c00000000000000000000000000000000000000000000000000000000825260a082600481865afa92831561488c57600092600094614891575b5060008312613ffa576020600491604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa92831561488c576127099363ffffffff9361482d93600092614856575b506020015160ff165b90614042565b9261484861483961059e565b6001600160e01b039095168552565b1663ffffffff166020830152565b61482791925061487d602091823d8411614885575b614875818361057b565b81019061474f565b92915061481e565b503d61486b565b614743565b9093506148b791925060a03d60a0116148c4575b6148af818361057b565b810190614711565b50939250509192386147c7565b503d6148a5565b929190926101608201937f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061494187517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614614a2b577f1e10bdc4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006149b387517fffffffff000000000000000000000000000000000000000000000000000000001690565b16146149e6576118e5613bcf86517fffffffff000000000000000000000000000000000000000000000000000000001690565b61270993945091614a21916117c79363ffffffff614a19610180614a11606087015163ffffffff1690565b950151151590565b9316916152ba565b5163ffffffff1690565b614a70939450614a436101e084015163ffffffff1690565b9063ffffffff614a68610180614a60606088015163ffffffff1690565b960151151590565b94169261567e565b5190565b9493919063ffffffff604087015116808211614b0657505061ffff60208601511690818111614ad05750507fffffffff0000000000000000000000000000000000000000000000000000000061016061022c9495015116615568565b61ffff92507fd88dddd6000000000000000000000000000000000000000000000000000000006000526004521660245260446000fd5b7f869337890000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b67ffffffffffffffff8116600052600560205260406000209160405192614b5c84610543565b546001600160e01b038116845260e01c9182602085015263ffffffff82169283614b96575b5050505061270990516001600160e01b031690565b63ffffffff164290810393908411612667578311614bb45780614b81565b7ff08bcb3e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045263ffffffff1660245260445260646000fd5b60408136031261021c57602060405191614c1083610543565b8035614c1b8161020b565b83520135602082015290565b9694919695929390956000946000986000986000965b808810614c51575050505050505050929190565b9091929394959697999a614c6e614c698a848b6127ae565b614bf7565b9a614cbc612b418d614ca5614c978967ffffffffffffffff16600052600a602052604060002090565b91516001600160a01b031690565b6001600160a01b0316600052602052604060002090565b91614ccd61173b60a0850151151590565b614e165760009c6040840190614ce8612298835161ffff1690565b614d9e575b5050606083015163ffffffff16614d039161382d565b9c6080830151614d169063ffffffff1690565b614d1f9161382d565b9b8251614d2f9063ffffffff1690565b63ffffffff16614d3e90612645565b60019390808310614d9257506123516117c76020614d6193015163ffffffff1690565b808211614d815750614d72916137ef565b985b0196959493929190614c3d565b9050614d8c916137ef565b98614d74565b915050614d8c916137ef565b9061213c614e07939f614df5614dfe9460208f8e61229895506001600160a01b03614dd085516001600160a01b031690565b91166001600160a01b03821614614e0f57614deb9150613997565b915b0151906156e6565b925161ffff1690565b620186a0900490565b9b3880614ced565b5091614ded565b999b5060019150614e3d84614e37614e4393614e318b612645565b906137ef565b9b61382d565b9c613815565b9a614d74565b91939093806101e00193846101e011612667576101208102908082046101201490151715612667576101e091010180931161266757612298610140614edf612709966dffffffffffffffffffffffffffff612225614eca614eb7614ee99a63ffffffff61213c9a16906137ef565b61213c6122986101208c015161ffff1690565b614e316117c76101008b015163ffffffff1690565b93015161ffff1690565b61266c565b604080516001600160a01b039283166020820190815292909316908301527fffffffffffffffffffff0000000000000000000000000000000000000000000090921660608201527fffff000000000000000000000000000000000000000000000000000000000000909216608083015290614f6c8160a08101612b81565b51902090565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110614fa6575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b909291928360041161021c57831161021c57600401916003190190565b9060041161021c5790600490565b9081602091031261021c575190565b9081604091031261021c5760206040519161502c83610543565b805183520151612806816109ea565b91615044612ca3565b50811561513a575061508561205d828061507f7fffffffff000000000000000000000000000000000000000000000000000000009587614f72565b95614fd8565b91167f181dcf100000000000000000000000000000000000000000000000000000000081036150c257508060208061270993518301019101615012565b7f97a657c90000000000000000000000000000000000000000000000000000000014615112577f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b8060208061512593518301019101615003565b61512d61059e565b9081526000602082015290565b91505067ffffffffffffffff61514e61059e565b911681526000602082015290565b6020604051917f181dcf100000000000000000000000000000000000000000000000000000000082840152805160248401520151151560448201526044815261270960648261057b565b604051906151b382610527565b60606080836000815260006020820152600060408201526000838201520152565b60208183031261021c5780359067ffffffffffffffff821161021c57019060a08282031261021c576040519161520983610527565b6152128161112e565b835261522060208201610b65565b60208401526040810135615233816109ea565b60408401526060810135606084015260808101359067ffffffffffffffff821161021c57019080601f8301121561021c57813561526f816109d2565b9261527d604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106152aa57505050608082015290565b8135815260209182019101615298565b6152c26151a6565b5081156153f5577f1f3b3aba000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061531e6153188585614ff5565b90614f72565b16036153cb578161533a9261533292614fd8565b8101906151d4565b91806153b5575b61538b5763ffffffff615358835163ffffffff1690565b16116153615790565b7f2e2b0c290000000000000000000000000000000000000000000000000000000060005260046000fd5b7fee433e990000000000000000000000000000000000000000000000000000000060005260046000fd5b506153c661173b6040840151151590565b615341565b7f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b7fb00b53dc0000000000000000000000000000000000000000000000000000000060005260046000fd5b907fffffffff0000000000000000000000000000000000000000000000000000000082167f2812d52c0000000000000000000000000000000000000000000000000000000081146154ed577f1e10bdc400000000000000000000000000000000000000000000000000000000146154e0577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000821660045260246000fd5b61022c9150600190615717565b50905060208151036155265761550c6020825183010160208301615003565b6001600160a01b03811190811561555c575b506155265750565b613f77906040519182917f8d666f6000000000000000000000000000000000000000000000000000000000835260048301615706565b6104009150103861551e565b917fffffffff0000000000000000000000000000000000000000000000000000000083167f2812d52c000000000000000000000000000000000000000000000000000000008114615636577f1e10bdc40000000000000000000000000000000000000000000000000000000014615629577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000831660045260246000fd5b61022c9250151590615717565b5050905060208151036155265761550c6020825183010160208301615003565b6001600160a01b036127099116600b615847565b6001600160a01b036127099116600b61597b565b9063ffffffff61569b93959495615693612ca3565b50169161503b565b918251116156bc57806156b0575b61538b5790565b506020810151156156a9565b7f4c4fc93a0000000000000000000000000000000000000000000000000000000060005260046000fd5b670de0b6b3a7640000916001600160e01b03615702921661268c565b0490565b9060206127099281815201906105bd565b90602082510361577f576157285750565b60208180518101031261021c576020810151156157425750565b613f77906040519182917fff828faa00000000000000000000000000000000000000000000000000000000835260206004840181815201906105bd565b6040517fff828faa0000000000000000000000000000000000000000000000000000000081526020600482015280613f7760248201856105bd565b80548210156127be5760005260206000200190600090565b916157ec918354906000199060031b92831b921b19161790565b9055565b8054801561581857600019019061580782826157ba565b60001982549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60018101918060005282602052604060002054928315156000146158f95760001984018481116126675783549360001985019485116126675760009585836158aa9761589b95036158b0575b5050506157f0565b90600052602052604060002090565b55600190565b6158e06158da916158d16158c76158f095886157ba565b90549060031b1c90565b928391876157ba565b906157d2565b8590600052602052604060002090565b55388080615893565b50505050600090565b8054906801000000000000000082101561052257816159299160016157ec940181556157ba565b81939154906000199060031b92831b921b19161790565b6000818152600360205260409020546159755761595e816002615902565b600254906000526003602052604060002055600190565b50600090565b60008281526001820160205260409020546159b2578061599d83600193615902565b80549260005201602052604060002055600190565b5050600090565b6000818152600360205260409020549081156159b257600019820190828211612667576002549260001984019384116126675783836158aa9460009603615a19575b505050615a0860026157f0565b600390600052602052604060002090565b615a086158da91615a316158c7615a3b9560026157ba565b92839160026157ba565b553880806159fb56fea164736f6c634300081a000a",
+ Bin: "0x60e06040523461106a576171a380380380610019816112d6565b928339810190808203610120811261106a5760601361106a5761003a611298565b81516001600160601b038116810361106a57815261005a602083016112fb565b906020810191825261006e6040840161130f565b6040820190815260608401516001600160401b03811161106a5785610094918601611337565b60808501519094906001600160401b03811161106a57866100b6918301611337565b60a08201519096906001600160401b03811161106a5782019080601f8301121561106a5781516100ed6100e882611320565b6112d6565b9260208085848152019260071b8201019083821161106a57602001915b8183106112235750505060c08301516001600160401b03811161106a5783019781601f8a01121561106a578851986101446100e88b611320565b996020808c838152019160051b8301019184831161106a5760208101915b8383106110c1575050505060e08401516001600160401b03811161106a5784019382601f8601121561106a57845161019c6100e882611320565b9560208088848152019260061b8201019085821161106a57602001915b81831061108557505050610100810151906001600160401b03821161106a570182601f8201121561106a578051906101f36100e883611320565b93602061028081878681520194028301019181831161106a57602001925b828410610ea857505050503315610e9757600180546001600160a01b031916331790556020986102408a6112d6565b976000895260003681376102526112b7565b998a52888b8b015260005b89518110156102c4576001906001600160a01b0361027b828d6113d0565b51168d610287826115bc565b610294575b50500161025d565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1388d61028c565b508a985089519660005b885181101561033f576001600160a01b036102e9828b6113d0565b511690811561032e577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef8c83610320600195611544565b50604051908152a1016102ce565b6342bcdf7f60e11b60005260046000fd5b5081518a985089906001600160a01b0316158015610e85575b8015610e76575b610e655791516001600160a01b031660a05290516001600160601b03166080525163ffffffff1660c052610392866112d6565b9360008552600036813760005b855181101561040e576001906103c76001600160a01b036103c0838a6113d0565b5116611451565b6103d2575b0161039f565b818060a01b036103e282896113d0565b51167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a26103cc565b508694508560005b84518110156104855760019061043e6001600160a01b0361043783896113d0565b5116611583565b610449575b01610416565b818060a01b0361045982886113d0565b51167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2610443565b508593508460005b835181101561054757806104a3600192866113d0565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf606089858060a01b038451169301518360005260078b5260406000209060ff878060a01b038251169283898060a01b03198254161781558d8301908151604082549501948460a81b8651151560a81b16918560a01b9060a01b169061ffff60a01b19161717905560405193845251168c8301525115156040820152a20161048d565b5091509160005b8251811015610afd5761056181846113d0565b51856001600160401b0361057584876113d0565b5151169101519080158015610aea575b8015610acc575b8015610a92575b610a7e57600081815260098852604090205460019392919060081b6001600160e01b03191661093657807f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806106fc868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a25b60005260098752826040600020825115158382549162ffff008c83015160081b169066ffffffff000000604084015160181b166affffffff00000000000000606085015160381b16926effffffff0000000000000000000000608086015160581b169260ff60781b60a087015160781b169460ff60801b60c088015160801b169161ffff60881b60e089015160881b169063ffffffff60981b6101008a015160981b169361ffff60b81b6101208b015160b81b169661ffff60c81b6101408c015160c81b169963ffffffff60d81b6101608d015160081c169b61018060ff60f81b910151151560f81b169c8f8060f81b039a63ffffffff60d81b199961ffff60c81b199861ffff60b81b199763ffffffff60981b199661ffff60881b199560ff60801b199460ff60781b19936effffffff0000000000000000000000199260ff6affffffff000000000000001992169066ffffffffffffff19161716171617161716171617161716171617161716179063ffffffff60d81b1617178155019061ffff6101a0820151169082549165ffffffff00006101c083015160101b169269ffffffff0000000000006101e084015160301b166a01000000000000000000008860901b0361020085015160501b169263ffffffff60901b61022086015160901b169461024063ffffffff60b01b91015160b01b169563ffffffff60b01b199363ffffffff60901b19926a01000000000000000000008c60901b0319918c8060501b03191617161716171617171790550161054e565b807f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e360405180610a76868291909161024063ffffffff8161026084019580511515855261ffff602082015116602086015282604082015116604086015282606082015116606086015282608082015116608086015260ff60a08201511660a086015260ff60c08201511660c086015261ffff60e08201511660e0860152826101008201511661010086015261ffff6101208201511661012086015261ffff610140820151166101408601528260e01b61016082015116610160860152610180810151151561018086015261ffff6101a0820151166101a0860152826101c0820151166101c0860152826101e0820151166101e086015260018060401b03610200820151166102008601528261022082015116610220860152015116910152565b0390a2610700565b63c35aa79d60e01b60005260045260246000fd5b5063ffffffff60e01b61016083015116630a04b54b60e21b8114159081610aba575b50610593565b6307842f7160e21b1415905088610ab4565b5063ffffffff6101e08301511663ffffffff6060840151161061058c565b5063ffffffff6101e08301511615610585565b84828560005b8151811015610b83576001906001600160a01b03610b2182856113d0565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d86848060401b0381610b5786896113d0565b510151168360005260088252604060002081878060401b0319825416179055604051908152a201610b03565b83600184610b90836112d6565b9060008252600092610e60575b909282935b8251851015610d9f57610bb585846113d0565b5180516001600160401b0316939083019190855b83518051821015610d8e57610bdf8287926113d0565b51015184516001600160a01b0390610bf89084906113d0565b5151169063ffffffff815116908781019163ffffffff8351169081811015610d795750506080810163ffffffff815116898110610d62575090899291838c52600a8a5260408c20600160a01b6001900386168d528a5260408c2092825163ffffffff169380549180518d1b67ffffffff0000000016916040860192835160401b69ffff000000000000000016966060810195865160501b6dffffffff00000000000000000000169063ffffffff60701b895160701b169260a001998b60ff60901b8c51151560901b169560ff60901b199363ffffffff60701b19926dffffffff000000000000000000001991600160501b60019003191617161716171617171790556040519586525163ffffffff168c8601525161ffff1660408501525163ffffffff1660608401525163ffffffff16608083015251151560a082015260c07f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b591a3600101610bc9565b6312766e0160e11b8c52600485905260245260448bfd5b6305a7b3d160e11b8c5260045260245260448afd5b505060019096019593509050610ba2565b9150825b8251811015610e21576001906001600160401b03610dc182866113d0565b515116828060a01b0384610dd584886113d0565b5101511690808752600a855260408720848060a01b038316885285528660408120557f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b8780a301610da3565b604051615b52908161165182396080518181816104420152612a3e015260a05181818161047801526129ef015260c05181818161049f01526137c90152f35b610b9d565b63d794ef9560e01b60005260046000fd5b5063ffffffff8251161561035f565b5080516001600160601b031615610358565b639b15e16f60e01b60005260046000fd5b838203610280811261106a57610260610ebf6112b7565b91610ec9876113ad565b8352601f19011261106a576040519161026083016001600160401b0381118482101761106f57604052610efe602087016113a0565b8352610f0c604087016113c1565b6020840152610f1d6060870161130f565b6040840152610f2e6080870161130f565b6060840152610f3f60a0870161130f565b6080840152610f5060c08701611392565b60a0840152610f6160e08701611392565b60c0840152610f7361010087016113c1565b60e0840152610f85610120870161130f565b610100840152610f9861014087016113c1565b610120840152610fab61016087016113c1565b610140840152610180860151916001600160e01b03198316830361106a5783602093610160610280960152610fe36101a089016113a0565b610180820152610ff66101c089016113c1565b6101a08201526110096101e0890161130f565b6101c082015261101c610200890161130f565b6101e082015261102f61022089016113ad565b610200820152611042610240890161130f565b610220820152611055610260890161130f565b61024082015283820152815201930192610211565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60408387031261106a57602060409161109c6112b7565b6110a5866112fb565b81526110b28387016113ad565b838201528152019201916101b9565b82516001600160401b03811161106a5782016040818803601f19011261106a576110e96112b7565b906110f6602082016113ad565b825260408101516001600160401b03811161106a57602091010187601f8201121561106a5780516111296100e882611320565b91602060e08185858152019302820101908a821161106a57602001915b8183106111655750505091816020938480940152815201920191610162565b828b0360e0811261106a5760c061117a6112b7565b91611184866112fb565b8352601f19011261106a576040519160c08301916001600160401b0383118484101761106f5760e0936020936040526111be84880161130f565b81526111cc6040880161130f565b848201526111dc606088016113c1565b60408201526111ed6080880161130f565b60608201526111fe60a0880161130f565b608082015261120f60c088016113a0565b60a082015283820152815201920191611146565b8284036080811261106a5760606112386112b7565b91611242866112fb565b8352601f19011261106a5760809160209161125b611298565b6112668488016112fb565b815261127460408801611392565b84820152611284606088016113a0565b60408201528382015281520192019161010a565b60405190606082016001600160401b0381118382101761106f57604052565b60408051919082016001600160401b0381118382101761106f57604052565b6040519190601f01601f191682016001600160401b0381118382101761106f57604052565b51906001600160a01b038216820361106a57565b519063ffffffff8216820361106a57565b6001600160401b03811161106f5760051b60200190565b9080601f8301121561106a5781516113516100e882611320565b9260208085848152019260051b82010192831161106a57602001905b82821061137a5750505090565b60208091611387846112fb565b81520191019061136d565b519060ff8216820361106a57565b5190811515820361106a57565b51906001600160401b038216820361106a57565b519061ffff8216820361106a57565b80518210156113e45760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156113e45760005260206000200190600090565b8054801561143b57600019019061142982826113fa565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6000818152600c602052604090205480156115125760001981018181116114fc57600b546000198101919082116114fc578181036114ab575b505050611497600b611412565b600052600c60205260006040812055600190565b6114e46114bc6114cd93600b6113fa565b90549060031b1c928392600b6113fa565b819391549060031b91821b91600019901b19161790565b9055600052600c60205260406000205538808061148a565b634e487b7160e01b600052601160045260246000fd5b5050600090565b8054906801000000000000000082101561106f57816114cd916001611540940181556113fa565b9055565b8060005260036020526040600020541560001461157d57611566816002611519565b600254906000526003602052604060002055600190565b50600090565b80600052600c6020526040600020541560001461157d576115a581600b611519565b600b5490600052600c602052604060002055600190565b60008181526003602052604090205480156115125760001981018181116114fc576002546000198101919082116114fc57808203611616575b5050506116026002611412565b600052600360205260006040812055600190565b6116386116276114cd9360026113fa565b90549060031b1c92839260026113fa565b905560005260036020526040600020553880806115f556fe6080604052600436101561001257600080fd5b60003560e01c806241e5be1461020657806301ffc9a714610201578063061877e3146101fc57806306285c69146101f7578063181f5a77146101f25780632451a627146101ed578063325c868e146101e85780633937306f146101e357806341ed29e7146101de578063430d138c146101d957806345ac924d146101d45780634ab35b0b146101cf578063514e8cff146101ca5780636def4ce7146101c5578063770e2dc4146101c057806379ba5097146101bb5780637afac322146101b6578063805f2132146101b157806382b49eb0146101ac57806387b8d879146101a75780638da5cb5b146101a257806391a2749a1461019d578063a69c64c014610198578063bf78e03f14610193578063cdc73d511461018e578063d02641a014610189578063d63d3af214610184578063d8694ccd1461017f578063f2fde38b1461017a578063fbe3f778146101755763ffdb4b371461017057600080fd5b612595565b612498565b6123dc565b611f78565b611f5c565b611f13565b611e9c565b611df6565b611d3d565b611ca9565b611c82565b611a66565b6118e9565b61164e565b611515565b6113fd565b6111de565b61105f565b610e88565b610e50565b610d87565b610c5a565b6109ff565b610743565b610727565b6106a4565b6105fe565b610406565b6103be565b61029a565b61022e565b6001600160a01b0381160361021c57565b600080fd5b359061022c8261020b565b565b3461021c57606060031936011261021c5760206102656004356102508161020b565b602435604435916102608361020b565b612717565b604051908152f35b35907fffffffff000000000000000000000000000000000000000000000000000000008216820361021c57565b3461021c57602060031936011261021c576004357fffffffff000000000000000000000000000000000000000000000000000000008116810361021c577fffffffff00000000000000000000000000000000000000000000000000000000602091167f805f2132000000000000000000000000000000000000000000000000000000008114908115610394575b811561036a575b8115610340575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610335565b7f181f5a77000000000000000000000000000000000000000000000000000000008114915061032e565b7f9b645f410000000000000000000000000000000000000000000000000000000081149150610327565b3461021c57602060031936011261021c576001600160a01b036004356103e38161020b565b166000526008602052602067ffffffffffffffff60406000205416604051908152f35b3461021c57600060031936011261021c5761041f61274b565b50606060405161042e81610506565b63ffffffff6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016918281526001600160a01b0360406020830192827f00000000000000000000000000000000000000000000000000000000000000001684520191837f00000000000000000000000000000000000000000000000000000000000000001683526040519485525116602084015251166040820152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761052257604052565b6104d7565b60a0810190811067ffffffffffffffff82111761052257604052565b6040810190811067ffffffffffffffff82111761052257604052565b60c0810190811067ffffffffffffffff82111761052257604052565b90601f601f19910116810190811067ffffffffffffffff82111761052257604052565b6040519061022c60408361057b565b6040519061022c6102608361057b565b919082519283825260005b8481106105e9575050601f19601f8460006020809697860101520116010190565b806020809284010151828286010152016105c8565b3461021c57600060031936011261021c5761065d6040805190610621818361057b565b601382527f46656551756f74657220312e362e302d646576000000000000000000000000006020830152519182916020835260208301906105bd565b0390f35b602060408183019282815284518094520192019060005b8181106106855750505090565b82516001600160a01b0316845260209384019390920191600101610678565b3461021c57600060031936011261021c5760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b8181106107115761065d856107058187038261057b565b60405191829182610661565b82548452602090930192600192830192016106ee565b3461021c57600060031936011261021c57602060405160248152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c5780600401906040600319823603011261021c57610781613b02565b61078b828061276a565b4263ffffffff1692915060005b8181106108fc575050602401906107af828461276a565b92905060005b8381106107be57005b806107dd6107d86001936107d2868a61276a565b906127ed565b61284d565b7fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e67ffffffffffffffff6108d86108ca60208501946108bc61082687516001600160e01b031690565b61084061083161059e565b6001600160e01b039092168252565b63ffffffff8c16602082015261087b610861845167ffffffffffffffff1690565b67ffffffffffffffff166000526005602052604060002090565b815160209092015160e01b7fffffffff00000000000000000000000000000000000000000000000000000000166001600160e01b0392909216919091179055565b5167ffffffffffffffff1690565b93516001600160e01b031690565b604080516001600160e01b039290921682524260208301529190931692a2016107b5565b806109156109106001936107d2898061276a565b612816565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036109ae6108ca60208501946109a161095d87516001600160e01b031690565b61096861083161059e565b63ffffffff8d16602082015261087b61098884516001600160a01b031690565b6001600160a01b03166000526006602052604060002090565b516001600160a01b031690565b604080516001600160e01b039290921682524260208301529190931692a201610798565b67ffffffffffffffff81116105225760051b60200190565b8015150361021c57565b359061022c826109ea565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590610a3c826109d2565b90610a4a604051928361057b565b828252602460a06020840194028201019036821161021c57602401925b818410610a7957610a7783612872565b005b60a08436031261021c5760405190610a9082610527565b8435610a9b8161020b565b825260208501357fffffffffffffffffffff000000000000000000000000000000000000000000008116810361021c5760208301526040850135907fffff0000000000000000000000000000000000000000000000000000000000008216820361021c5782602092604060a0950152610b1660608801610221565b6060820152610b27608088016109f4565b6080820152815201930192610a67565b6004359067ffffffffffffffff8216820361021c57565b6024359067ffffffffffffffff8216820361021c57565b359067ffffffffffffffff8216820361021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020838186019501011161021c57565b9181601f8401121561021c5782359167ffffffffffffffff831161021c576020808501948460051b01011161021c57565b929091610bfa928452151560208401526080604084015260808301906105bd565b906060818303910152815180825260208201916020808360051b8301019401926000915b838310610c2d57505050505090565b9091929394602080610c4b83601f19866001960301875289516105bd565b97019301930191939290610c1e565b3461021c5760c060031936011261021c57610c73610b37565b60243590610c808261020b565b60443560643567ffffffffffffffff811161021c57610ca3903690600401610b7a565b60849391933567ffffffffffffffff811161021c57610cc6903690600401610ba8565b9160a4359567ffffffffffffffff871161021c573660238801121561021c5786600401359567ffffffffffffffff871161021c573660248860061b8a01011161021c5761065d986024610d1a9901966129e4565b9060409492945194859485610bd9565b602060408183019282815284518094520192019060005b818110610d4e5750505090565b9091926020604082610d7c600194885163ffffffff602080926001600160e01b038151168552015116910152565b019401929101610d41565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c57610db8903690600401610ba8565b610dc1816109d2565b91610dcf604051938461057b565b818352601f19610dde836109d2565b0160005b818110610e3957505060005b82811015610e2b57600190610e0f610e0a8260051b8501612cfb565b613775565b610e1982876129d0565b52610e2481866129d0565b5001610dee565b6040518061065d8682610d2a565b602090610e44612ce2565b82828801015201610de2565b3461021c57602060031936011261021c576020610e77600435610e728161020b565b613a8a565b6001600160e01b0360405191168152f35b3461021c57602060031936011261021c5767ffffffffffffffff610eaa610b37565b610eb2612ce2565b50166000526005602052604060002060405190610ece82610543565b546001600160e01b038116825260e01c6020820152604051809161065d82604081019263ffffffff602080926001600160e01b038151168552015116910152565b61022c9092919261024080610260830195610f2c84825115159052565b60208181015161ffff169085015260408181015163ffffffff169085015260608181015163ffffffff169085015260808181015163ffffffff169085015260a08181015160ff169085015260c08181015160ff169085015260e08181015161ffff16908501526101008181015163ffffffff16908501526101208181015161ffff16908501526101408181015161ffff1690850152610160818101517fffffffff000000000000000000000000000000000000000000000000000000001690850152610180818101511515908501526101a08181015161ffff16908501526101c08181015163ffffffff16908501526101e08181015163ffffffff16908501526102008181015167ffffffffffffffff16908501526102208181015163ffffffff1690850152015163ffffffff16910152565b3461021c57602060031936011261021c5761065d61112261111d611081610b37565b600061024061108e6105ad565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a0820152826101c0820152826101e08201528261020082015282610220820152015267ffffffffffffffff166000526009602052604060002090565b612d2a565b60405191829182610f0f565b359063ffffffff8216820361021c57565b359061ffff8216820361021c57565b81601f8201121561021c57803590611165826109d2565b92611173604051948561057b565b82845260208085019360061b8301019181831161021c57602001925b82841061119d575050505090565b60408483031261021c57602060409182516111b781610543565b6111c087610b65565b8152828701356111cf8161020b565b8382015281520193019261118f565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013561121a816109d2565b91611228604051938461057b565b8183526024602084019260051b8201019036821161021c5760248101925b828410611277576024358567ffffffffffffffff821161021c57611271610a7792369060040161114e565b90612e98565b833567ffffffffffffffff811161021c57820160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc823603011261021c57604051906112c382610543565b6112cf60248201610b65565b8252604481013567ffffffffffffffff811161021c57602491010136601f8201121561021c578035611300816109d2565b9161130e604051938461057b565b818352602060e081850193028201019036821161021c57602001915b8183106113495750505091816020938480940152815201930192611246565b82360360e0811261021c5760c0601f196040519261136684610543565b86356113718161020b565b8452011261021c5760e09160209160405161138b8161055f565b61139684880161112e565b81526113a46040880161112e565b848201526113b46060880161113f565b60408201526113c56080880161112e565b60608201526113d660a0880161112e565b608082015260c08701356113e9816109ea565b60a08201528382015281520192019161132a565b3461021c57600060031936011261021c576000546001600160a01b0381163303611484577fffffffffffffffffffffffff0000000000000000000000000000000000000000600154913382841617600155166000556001600160a01b033391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b9080601f8301121561021c5781356114c5816109d2565b926114d3604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106114fb5750505090565b60208091833561150a8161020b565b8152019101906114ee565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c576115469036906004016114ae565b60243567ffffffffffffffff811161021c576115669036906004016114ae565b9061156f613b46565b60005b81518110156115de578061159361158e6109a1600194866129d0565b615757565b61159e575b01611572565b6001600160a01b036115b36109a183866129d0565b167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a2611598565b8260005b8151811015610a7757806116036115fe6109a1600194866129d0565b61576b565b61160e575b016115e2565b6001600160a01b036116236109a183866129d0565b167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2611608565b3461021c57604060031936011261021c5760043567ffffffffffffffff811161021c5761167f903690600401610b7a565b6024359167ffffffffffffffff831161021c576116d86116d06116b66116ac6116e0963690600401610b7a565b9490953691613147565b90604082015190605e604a84015160601c93015191929190565b919033613faa565b81019061318e565b60005b8151811015610a775761172b61172661170d6116ff84866129d0565b51516001600160a01b031690565b6001600160a01b03166000526007602052604060002090565b61324d565b61173f61173b6040830151151590565b1590565b6118a0579061178a6117576020600194015160ff1690565b611784611778602061176986896129d0565b5101516001600160e01b031690565b6001600160e01b031690565b9061407c565b6117a5604061179984876129d0565b51015163ffffffff1690565b63ffffffff6117d06117c76117c06109886116ff888b6129d0565b5460e01c90565b63ffffffff1690565b91161061189a5761181e6117e9604061179985886129d0565b61180e6117f461059e565b6001600160e01b03851681529163ffffffff166020830152565b61087b6109886116ff86896129d0565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a6001600160a01b036118546116ff85886129d0565b6118906118666040611799888b6129d0565b60405193849316958390929163ffffffff6020916001600160e01b03604085019616845216910152565b0390a25b016116e3565b50611894565b6118e56118b06116ff84866129d0565b7f06439c6b000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b6000fd5b3461021c57604060031936011261021c5761065d611971611908610b37565b67ffffffffffffffff6024359161191e8361020b565b600060a060405161192e8161055f565b828152826020820152826040820152826060820152826080820152015216600052600a6020526040600020906001600160a01b0316600052602052604060002090565b6119ed6119e4604051926119848461055f565b5463ffffffff8116845263ffffffff8160201c16602085015261ffff8160401c1660408501526119cb6119be8263ffffffff9060501c1690565b63ffffffff166060860152565b63ffffffff607082901c16608085015260901c60ff1690565b151560a0830152565b6040519182918291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b60ff81160361021c57565b359061022c82611a50565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611aa3826109d2565b90611ab1604051928361057b565b82825260246102806020840194028201019036821161021c57602401925b818410611adf57610a77836132dd565b833603610280811261021c57610260601f1960405192611afe84610543565b611b0788610b65565b8452011261021c5761028091602091611b1e6105ad565b611b298489016109f4565b8152611b376040890161113f565b84820152611b476060890161112e565b6040820152611b586080890161112e565b6060820152611b6960a0890161112e565b6080820152611b7a60c08901611a5b565b60a0820152611b8b60e08901611a5b565b60c0820152611b9d610100890161113f565b60e0820152611baf610120890161112e565b610100820152611bc2610140890161113f565b610120820152611bd5610160890161113f565b610140820152611be8610180890161026d565b610160820152611bfb6101a089016109f4565b610180820152611c0e6101c0890161113f565b6101a0820152611c216101e0890161112e565b6101c0820152611c34610200890161112e565b6101e0820152611c476102208901610b65565b610200820152611c5a610240890161112e565b610220820152611c6d610260890161112e565b61024082015283820152815201930192611acf565b3461021c57600060031936011261021c5760206001600160a01b0360015416604051908152f35b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c576040600319823603011261021c57604051611ce681610543565b816004013567ffffffffffffffff811161021c57611d0a90600436918501016114ae565b8152602482013567ffffffffffffffff811161021c57610a77926004611d3392369201016114ae565b6020820152613547565b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c57806004013590611d7a826109d2565b90611d88604051928361057b565b8282526024602083019360061b8201019036821161021c57602401925b818410611db557610a7783613699565b60408436031261021c5760206040918251611dcf81610543565b8635611dda8161020b565b8152611de7838801610b65565b83820152815201930192611da5565b3461021c57602060031936011261021c576001600160a01b03600435611e1b8161020b565b611e2361274b565b5016600052600760205261065d604060002060ff60405191611e4483610506565b546001600160a01b0381168352818160a01c16602084015260a81c16151560408201526040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b3461021c57600060031936011261021c57604051806020600b54918281520190600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99060005b818110611efd5761065d856107058187038261057b565b8254845260209093019260019283019201611ee6565b3461021c57602060031936011261021c576040611f35600435610e0a8161020b565b611f5a8251809263ffffffff602080926001600160e01b038151168552015116910152565bf35b3461021c57600060031936011261021c57602060405160128152f35b3461021c57604060031936011261021c57611f91610b37565b60243567ffffffffffffffff811161021c57806004019060a0600319823603011261021c57611fd761111d8467ffffffffffffffff166000526009602052604060002090565b611fe461173b8251151590565b6123a4576064820161201a61173b611ffb83612cfb565b6001600160a01b03166000526001600b01602052604060002054151590565b612363579083916044840195612030878561276a565b9590506120716024820191612054608461204a858a613891565b9390500188613891565b908961206a6120638b80613891565b3691613147565b93896149be565b928461207f610e7283612cfb565b98899461209d61209761022085015163ffffffff1690565b82614c37565b9b6000808c1561232957505061210361ffff856121289961210f99989661214396612136966120fa6120ea6101c06120de6101a06121499f015161ffff1690565b97015163ffffffff1690565b916120f48c612cfb565b9461276a565b96909516614d28565b98919897909894612cfb565b6001600160a01b03166000526008602052604060002090565b5467ffffffffffffffff1690565b67ffffffffffffffff1690565b906126cb565b9560009761ffff61216061014089015161ffff1690565b166122ce575b509461214361213661020061223461065d9d6dffffffffffffffffffffffffffff61222c61224c9f9e9b6122276001600160e01b039f9b9c6122449f6122279e63ffffffff6121bb6122279f6121c594613891565b92905016906138e2565b908b60a081016121e86121e26121dc835160ff1690565b60ff1690565b856126cb565b9360e08301916121fa835161ffff1690565b9061ffff8216831161225c575b5050505060800151612227916117c79163ffffffff16613920565b613920565b6138e2565b9116906126cb565b93015167ffffffffffffffff1690565b9116906126de565b6040519081529081906020820190565b6117c7949650612227959361ffff6122bd6122ac612222966122a661229f61229660809960ff6122906122c49b5160ff1690565b166138ef565b965161ffff1690565b61ffff1690565b90613768565b6121436121dc60c08d015160ff1690565b91166138e2565b9593839550612207565b909594989750826122f48b989495986dffffffffffffffffffffffffffff9060701c1690565b6dffffffffffffffffffffffffffff169161230f8489613891565b905061231b9388614f4a565b969793943896939296612166565b969593509650505061214361213661212861210f61235d6123586117c761024061214999015163ffffffff1690565b612684565b94612cfb565b61236f6118e591612cfb565b7f2502348c000000000000000000000000000000000000000000000000000000006000526001600160a01b0316600452602490565b7f99ac52f20000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff841660045260246000fd5b3461021c57602060031936011261021c576001600160a01b036004356124018161020b565b612409613b46565b1633811461246e57807fffffffffffffffffffffffff000000000000000000000000000000000000000060005416176000556001600160a01b03600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b3461021c57602060031936011261021c5760043567ffffffffffffffff811161021c573660238201121561021c578060040135906124d5826109d2565b906124e3604051928361057b565b8282526024602083019360071b8201019036821161021c57602401925b81841061251057610a778361393a565b8336036080811261021c576060601f196040519261252d84610543565b87356125388161020b565b8452011261021c5760809160209160405161255281610506565b8388013561255f8161020b565b8152604088013561256f81611a50565b848201526060880135612581816109ea565b604082015283820152815201930192612500565b3461021c57604060031936011261021c576004356125b28161020b565b6125ba610b4e565b9067ffffffffffffffff82169182600052600960205260ff6040600020541615612627576125ea61260b92613a8a565b92600052600960205263ffffffff60016040600020015460901c1690614c37565b604080516001600160e01b039384168152919092166020820152f35b827f99ac52f20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90662386f26fc10000820291808304662386f26fc1000014901517156126a657565b612655565b90655af3107a4000820291808304655af3107a400014901517156126a657565b818102929181159184041417156126a657565b81156126e8570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b61274161273b61274894936001600160e01b036127348195613a8a565b16906126cb565b92613a8a565b16906126de565b90565b6040519061275882610506565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c57602001918160061b3603831361021c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156127fd5760061b0190565b6127be565b35906001600160e01b038216820361021c57565b60408136031261021c5761284560206040519261283284610543565b803561283d8161020b565b845201612802565b602082015290565b60408136031261021c5761284560206040519261286984610543565b61283d81610b65565b9061287b613b46565b60005b82518110156129cb5780612894600192856129d0565b517f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a360a06001600160a01b038351169260608101936001600160a01b0380865116957fffff00000000000000000000000000000000000000000000000000000000000061293260208601947fffffffffffffffffffff00000000000000000000000000000000000000000000865116604088019a848c511692614fef565b977fffffffffffffffffffff00000000000000000000000000000000000000000000608087019561299e875115158c600052600460205260406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b8560405198511688525116602087015251166040850152511660608301525115156080820152a20161287e565b509050565b80518210156127fd5760209160051b010190565b9895979692949391907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0382166001600160a01b03821614600014612cd2575050935b6bffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016808611612ca1575090612a74918715158a613b84565b979096612ac1612a988367ffffffffffffffff166000526009602052604060002090565b5460081b7fffffffff000000000000000000000000000000000000000000000000000000001690565b90612acb81613dcd565b9760005b828110612ae3575050505050505093929190565b612af6612af18284896127ed565b612cfb565b8388612b10612b06858484613e16565b6040810190613891565b905060208111612c26575b508392612b4a612b44612063612b3a600198612b8597612b8097613e16565b6020810190613891565b89615520565b612b688967ffffffffffffffff16600052600a602052604060002090565b906001600160a01b0316600052602052604060002090565b613283565b60a081015115612bea57612bce612ba66060612bc093015163ffffffff1690565b6040805163ffffffff909216602083015290928391820190565b03601f19810183528261057b565b612bd8828d6129d0565b52612be3818c6129d0565b5001612acf565b50612bc0612bce612c2184612c138a67ffffffffffffffff166000526009602052604060002090565b015460101c63ffffffff1690565b612ba6565b915050612c5e6117c7612c5184612b688b67ffffffffffffffff16600052600a602052604060002090565b5460701c63ffffffff1690565b10612c6b57838838612b1b565b7f36f536ca000000000000000000000000000000000000000000000000000000006000526001600160a01b031660045260246000fd5b857f6a92a4830000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b91612cdc92612717565b93612a2f565b60405190612cef82610543565b60006020838281520152565b356127488161020b565b90604051612d1281610543565b91546001600160e01b038116835260e01c6020830152565b9061022c612e8a6001612d3b6105ad565b94612e29612e1f8254612d57612d518260ff1690565b15158a52565b61ffff600882901c1660208a015263ffffffff601882901c1660408a015263ffffffff603882901c1660608a015263ffffffff605882901c1660808a015260ff607882901c1660a08a015260ff608082901c1660c08a015261ffff608882901c1660e08a015263ffffffff609882901c166101008a015261ffff60b882901c166101208a015261ffff60c882901c166101408a01527fffffffff00000000000000000000000000000000000000000000000000000000600882901b166101608a015260f81c90565b1515610180880152565b015461ffff81166101a086015263ffffffff601082901c166101c086015263ffffffff603082901c166101e086015267ffffffffffffffff605082901c1661020086015263ffffffff609082901c1661022086015260b01c63ffffffff1690565b63ffffffff16610240840152565b90612ea1613b46565b6000915b805183101561309357612eb883826129d0565b5190612ecc825167ffffffffffffffff1690565b946020600093019367ffffffffffffffff8716935b8551805182101561307e57612ef8826020926129d0565b510151612f096116ff8389516129d0565b8151602083015163ffffffff908116911681811015613045575050608082015163ffffffff1660208110613004575090867f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b56001600160a01b0384612f93858f60019998612b68612f8e9267ffffffffffffffff16600052600a602052604060002090565b613e56565b612ffb60405192839216958291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b0390a301612ee1565b7f24ecdc02000000000000000000000000000000000000000000000000000000006000526001600160a01b0390911660045263ffffffff1660245260446000fd5b7f0b4f67a20000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b50509550925092600191500191929092612ea5565b50905060005b815181101561314357806130c16130b2600193856129d0565b515167ffffffffffffffff1690565b67ffffffffffffffff6001600160a01b036130f060206130e186896129d0565b5101516001600160a01b031690565b600061311482612b688767ffffffffffffffff16600052600a602052604060002090565b551691167f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b600080a301613099565b5050565b92919267ffffffffffffffff82116105225760405191613171601f8201601f19166020018461057b565b82948184528183011161021c578281602093846000960137010152565b60208183031261021c5780359067ffffffffffffffff821161021c570181601f8201121561021c578035906131c2826109d2565b926131d0604051948561057b565b8284526020606081860194028301019181831161021c57602001925b8284106131fa575050505090565b60608483031261021c57602060609160405161321581610506565b86356132208161020b565b815261322d838801612802565b8382015261323d6040880161112e565b60408201528152019301926131ec565b9060405161325a81610506565b604060ff8294546001600160a01b0381168452818160a01c16602085015260a81c161515910152565b9061022c6040516132938161055f565b925463ffffffff8082168552602082811c821690860152604082811c61ffff1690860152605082901c81166060860152607082901c16608085015260901c60ff16151560a0840152565b906132e6613b46565b60005b82518110156129cb576132fc81846129d0565b51602061330c6130b284876129d0565b9101519067ffffffffffffffff811680158015613528575b80156134fa575b801561344d575b61341557916133db826001959461338b613366612a986133e09767ffffffffffffffff166000526009602052604060002090565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b6133e6577f71e9302ab4e912a9678ae7f5a8542856706806f2817e1bf2a20b171e265cb4ad604051806133be8782610f0f565b0390a267ffffffffffffffff166000526009602052604060002090565b614189565b016132e9565b7f2431cc0363f2f66b21782c7e3d54dd9085927981a21bd0cc6be45a51b19689e3604051806133be8782610f0f565b7fc35aa79d0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff821660045260246000fd5b507fffffffff0000000000000000000000000000000000000000000000000000000061349d6101608501517fffffffff000000000000000000000000000000000000000000000000000000001690565b167f2812d52c0000000000000000000000000000000000000000000000000000000081141590816134cf575b50613332565b7f1e10bdc40000000000000000000000000000000000000000000000000000000091501415386134c9565b506101e083015163ffffffff1663ffffffff6135206117c7606087015163ffffffff1690565b91161161332b565b5063ffffffff6135406101e085015163ffffffff1690565b1615613324565b61354f613b46565b60208101519160005b83518110156135dc57806135716109a1600193876129d0565b61359361358e6001600160a01b0383165b6001600160a01b031690565b615aba565b61359f575b5001613558565b6040516001600160a01b039190911681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758090602090a138613598565b5091505160005b8151811015613143576135f96109a182846129d0565b906001600160a01b0382161561366f577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef6136668361364b6136466135826001976001600160a01b031690565b615a41565b506040516001600160a01b0390911681529081906020820190565b0390a1016135e3565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b6136a1613b46565b60005b815181101561314357806001600160a01b036136c2600193856129d0565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d61375f67ffffffffffffffff60206136fe86896129d0565b51015116836000526008602052604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519182918291909167ffffffffffffffff6020820193169052565b0390a2016136a4565b919082039182116126a657565b61377d612ce2565b506137a361379e826001600160a01b03166000526006602052604060002090565b612d05565b60208101916137c26137bc6117c7855163ffffffff1690565b42613768565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000161161386a5761172661380e916001600160a01b03166000526007602052604060002090565b61381e61173b6040830151151590565b8015613870575b61386a5761383290614857565b9163ffffffff61385a6117c761384f602087015163ffffffff1690565b935163ffffffff1690565b911610613865575090565b905090565b50905090565b506001600160a01b0361388a82516001600160a01b031690565b1615613825565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561021c570180359067ffffffffffffffff821161021c5760200191813603831361021c57565b919082018092116126a657565b9061ffff8091169116029061ffff82169182036126a657565b63ffffffff60209116019063ffffffff82116126a657565b9063ffffffff8091169116019063ffffffff82116126a657565b90613943613b46565b60005b82518110156129cb578061395c600192856129d0565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf613a8160206001600160a01b0384511693015183600052600760205260406000206139e16001600160a01b0383511682906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b602082015181547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000075ff0000000000000000000000000000000000000000006040870151151560a81b169360a01b169116171790556040519182918291909160408060608301946001600160a01b03815116845260ff602082015116602085015201511515910152565b0390a201613946565b613a9381613775565b9063ffffffff602083015116158015613af0575b613ab95750516001600160e01b031690565b6001600160a01b03907f06439c6b000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b506001600160e01b0382511615613aa7565b33600052600360205260406000205415613b1857565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6001600160a01b03600154163303613b5a57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b61111d613baa91959493929567ffffffffffffffff166000526009602052604060002090565b936101608501947f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613c1d88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613d99577f1e10bdc4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000613c8f88517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614613d10576118e5613cc287517fffffffff000000000000000000000000000000000000000000000000000000001690565b7f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff0000000000000000000000000000000000000000000000000000000016600452602490565b60609192939495508063ffffffff613d3f610180613d3786613d4896015163ffffffff1690565b930151151590565b911686866153bb565b015181613d90575b50613d6657613d60913691613147565b90600190565b7f5bed51920000000000000000000000000000000000000000000000000000000060005260046000fd5b90501538613d50565b6101e00151939450613dbe93919291613db8915063ffffffff166117c7565b9161513c565b906127486020613d378461525d565b90613dd7826109d2565b613de4604051918261057b565b828152601f19613df482946109d2565b019060005b828110613e0557505050565b806060602080938501015201613df9565b91908110156127fd5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618136030182121561021c570190565b815181546020808501516040808701517fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000090941663ffffffff958616179190921b67ffffffff00000000161791901b69ffff000000000000000016178255606083015161022c93613f669260a092613f08911685547fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff1660509190911b6dffffffff0000000000000000000016178555565b613f5f613f1c608083015163ffffffff1690565b85547fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff1660709190911b71ffffffff000000000000000000000000000016178555565b0151151590565b81547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1690151560901b72ff00000000000000000000000000000000000016179055565b91929092613fba82828686614fef565b600052600460205260ff6040600020541615613fd65750505050565b6040517f097e17ff0000000000000000000000000000000000000000000000000000000081526001600160a01b0393841660048201529390921660248401527fffffffffffffffffffff0000000000000000000000000000000000000000000090911660448301527fffff000000000000000000000000000000000000000000000000000000000000166064820152608490fd5b0390fd5b604d81116126a657600a0a90565b60ff1660120160ff81116126a65760ff16906024821115614117577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc82019182116126a6576140cd6140d39261406e565b906126de565b6001600160e01b0381116140ed576001600160e01b031690565b7f10cb51d10000000000000000000000000000000000000000000000000000000060005260046000fd5b9060240390602482116126a6576121436141309261406e565b6140d3565b9060ff80911691160160ff81116126a65760ff16906024821115614117577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc82019182116126a6576140cd6140d39261406e565b906147a3610240600161022c946141d46141a38651151590565b829060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b61421a6141e6602087015161ffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1660089190911b62ffff0016178255565b61426661422e604087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffff1660189190911b66ffffffff00000016178255565b6142b661427a606087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffff1660389190911b6affffffff0000000000000016178255565b61430a6142ca608087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff1660589190911b6effffffff000000000000000000000016178255565b61435c61431b60a087015160ff1690565b82547fffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffff1660789190911b6fff00000000000000000000000000000016178255565b6143af61436d60c087015160ff1690565b82547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff1660809190911b70ff0000000000000000000000000000000016178255565b6144056143c160e087015161ffff1690565b82547fffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffffff1660889190911b72ffff000000000000000000000000000000000016178255565b61446261441a61010087015163ffffffff1690565b82547fffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffff1660989190911b76ffffffff0000000000000000000000000000000000000016178255565b6144bf61447561012087015161ffff1690565b82547fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff1660b89190911b78ffff000000000000000000000000000000000000000000000016178255565b61451e6144d261014087015161ffff1690565b82547fffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff1660c89190911b7affff0000000000000000000000000000000000000000000000000016178255565b61459f61454f6101608701517fffffffff000000000000000000000000000000000000000000000000000000001690565b82547fff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff1660089190911c7effffffff00000000000000000000000000000000000000000000000000000016178255565b6146006145b0610180870151151590565b82547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690151560f81b7fff0000000000000000000000000000000000000000000000000000000000000016178255565b01926146446146156101a083015161ffff1690565b859061ffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000825416179055565b6146906146596101c083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff1660109190911b65ffffffff000016178555565b6146e06146a56101e083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1660309190911b69ffffffff00000000000016178555565b61473c6146f961020083015167ffffffffffffffff1690565b85547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178555565b61479861475161022083015163ffffffff1690565b85547fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff1660909190911b75ffffffff00000000000000000000000000000000000016178555565b015163ffffffff1690565b7fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff79ffffffff0000000000000000000000000000000000000000000083549260b01b169116179055565b519069ffffffffffffffffffff8216820361021c57565b908160a091031261021c57614818816147ed565b916020820151916040810151916127486080606084015193016147ed565b6040513d6000823e3d90fd5b9081602091031261021c575161274881611a50565b61485f612ce2565b5061487761358261358283516001600160a01b031690565b90604051907ffeaf968c00000000000000000000000000000000000000000000000000000000825260a082600481865afa92831561497f57600092600094614984575b50600083126140ed576020600491604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa92831561497f576127489363ffffffff9361492093600092614949575b506020015160ff165b90614135565b9261493b61492c61059e565b6001600160e01b039095168552565b1663ffffffff166020830152565b61491a919250614970602091823d8411614978575b614968818361057b565b810190614842565b929150614911565b503d61495e565b614836565b9093506149aa91925060a03d60a0116149b7575b6149a2818361057b565b810190614804565b50939250509192386148ba565b503d614998565b91939492906149d76117c7604085015163ffffffff1690565b808211614c07575050602082015161ffff16808511614bd15750610160820193614a2185517fffffffff000000000000000000000000000000000000000000000000000000001690565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f2812d52c000000000000000000000000000000000000000000000000000000008103614aeb5750505081614abb91614ae696614a8e6101e0612748989796015163ffffffff1690565b9063ffffffff614ab3610180614aab606088015163ffffffff1690565b960151151590565b94169261577f565b519384925b517fffffffff000000000000000000000000000000000000000000000000000000001690565b615669565b94969195947f1e10bdc40000000000000000000000000000000000000000000000000000000003614b82575090829163ffffffff614b41610180614b396060614b4998015163ffffffff1690565b950151151590565b9316916153bb565b91151580614b76575b613d6657614ae692614b6e6117c7612748945163ffffffff1690565b938492614ac0565b50606082015115614b52565b7f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff000000000000000000000000000000000000000000000000000000001660045260246000fd5b7fd88dddd600000000000000000000000000000000000000000000000000000000600052600485905261ffff1660245260446000fd5b7f869337890000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b67ffffffffffffffff8116600052600560205260406000209160405192614c5d84610543565b546001600160e01b038116845260e01c9182602085015263ffffffff82169283614c97575b5050505061274890516001600160e01b031690565b63ffffffff1642908103939084116126a6578311614cb55780614c82565b7ff08bcb3e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045263ffffffff1660245260445260646000fd5b60408136031261021c57602060405191614d1183610543565b8035614d1c8161020b565b83520135602082015290565b9694919695929390956000946000986000986000965b808810614d52575050505050505050929190565b9091929394959697999a614d6f614d6a8a848b6127ed565b614cf8565b9a614dbd612b808d614da6614d988967ffffffffffffffff16600052600a602052604060002090565b91516001600160a01b031690565b6001600160a01b0316600052602052604060002090565b91614dce61173b60a0850151151590565b614f175760009c6040840190614de961229f835161ffff1690565b614e9f575b5050606083015163ffffffff16614e0491613920565b9c6080830151614e179063ffffffff1690565b614e2091613920565b9b8251614e309063ffffffff1690565b63ffffffff16614e3f90612684565b60019390808310614e9357506123586117c76020614e6293015163ffffffff1690565b808211614e825750614e73916138e2565b985b0196959493929190614d3e565b9050614e8d916138e2565b98614e75565b915050614e8d916138e2565b90612143614f08939f614ef6614eff9460208f8e61229f95506001600160a01b03614ed185516001600160a01b031690565b91166001600160a01b03821614614f1057614eec9150613a8a565b915b0151906157e7565b925161ffff1690565b620186a0900490565b9b3880614dee565b5091614eee565b999b5060019150614f3e84614f38614f4493614f328b612684565b906138e2565b9b613920565b9c613908565b9a614e75565b91939093806101e00193846101e0116126a65761012081029080820461012014901517156126a6576101e09101018093116126a65761229f610140614fe0612748966dffffffffffffffffffffffffffff61222c614fcb614fb8614fea9a63ffffffff6121439a16906138e2565b61214361229f6101208c015161ffff1690565b614f326117c76101008b015163ffffffff1690565b93015161ffff1690565b6126ab565b604080516001600160a01b039283166020820190815292909316908301527fffffffffffffffffffff0000000000000000000000000000000000000000000090921660608201527fffff00000000000000000000000000000000000000000000000000000000000090921660808301529061506d8160a08101612bc0565b51902090565b919091357fffffffff00000000000000000000000000000000000000000000000000000000811692600481106150a7575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b909291928360041161021c57831161021c57600401916003190190565b9060041161021c5790600490565b9081602091031261021c575190565b9081604091031261021c5760206040519161512d83610543565b805183520151612845816109ea565b91615145612ce2565b50811561523b575061518661206382806151807fffffffff000000000000000000000000000000000000000000000000000000009587615073565b956150d9565b91167f181dcf100000000000000000000000000000000000000000000000000000000081036151c357508060208061274893518301019101615113565b7f97a657c90000000000000000000000000000000000000000000000000000000014615213577f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b8060208061522693518301019101615104565b61522e61059e565b9081526000602082015290565b91505067ffffffffffffffff61524f61059e565b911681526000602082015290565b6020604051917f181dcf100000000000000000000000000000000000000000000000000000000082840152805160248401520151151560448201526044815261274860648261057b565b604051906152b482610527565b60606080836000815260006020820152600060408201526000838201520152565b60208183031261021c5780359067ffffffffffffffff821161021c57019060a08282031261021c576040519161530a83610527565b6153138161112e565b835261532160208201610b65565b60208401526040810135615334816109ea565b60408401526060810135606084015260808101359067ffffffffffffffff821161021c57019080601f8301121561021c578135615370816109d2565b9261537e604051948561057b565b81845260208085019260051b82010192831161021c57602001905b8282106153ab57505050608082015290565b8135815260209182019101615399565b6153c36152a7565b5081156154f6577f1f3b3aba000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061541f61541985856150f6565b90615073565b16036154cc578161543b92615433926150d9565b8101906152d5565b91806154b6575b61548c5763ffffffff615459835163ffffffff1690565b16116154625790565b7f2e2b0c290000000000000000000000000000000000000000000000000000000060005260046000fd5b7fee433e990000000000000000000000000000000000000000000000000000000060005260046000fd5b506154c761173b6040840151151590565b615442565b7f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b7fb00b53dc0000000000000000000000000000000000000000000000000000000060005260046000fd5b907fffffffff0000000000000000000000000000000000000000000000000000000082167f2812d52c0000000000000000000000000000000000000000000000000000000081146155ee577f1e10bdc400000000000000000000000000000000000000000000000000000000146155e1577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000821660045260246000fd5b61022c9150600190615818565b50905060208151036156275761560d6020825183010160208301615104565b6001600160a01b03811190811561565d575b506156275750565b61406a906040519182917f8d666f6000000000000000000000000000000000000000000000000000000000835260048301615807565b6104009150103861561f565b917fffffffff0000000000000000000000000000000000000000000000000000000083167f2812d52c000000000000000000000000000000000000000000000000000000008114615737577f1e10bdc4000000000000000000000000000000000000000000000000000000001461572a577f2ee82075000000000000000000000000000000000000000000000000000000006000527fffffffff00000000000000000000000000000000000000000000000000000000831660045260246000fd5b61022c9250151590615818565b5050905060208151036156275761560d6020825183010160208301615104565b6001600160a01b036127489116600b615948565b6001600160a01b036127489116600b615a7c565b9063ffffffff61579c93959495615794612ce2565b50169161513c565b918251116157bd57806157b1575b61548c5790565b506020810151156157aa565b7f4c4fc93a0000000000000000000000000000000000000000000000000000000060005260046000fd5b670de0b6b3a7640000916001600160e01b0361580392166126cb565b0490565b9060206127489281815201906105bd565b906020825103615880576158295750565b60208180518101031261021c576020810151156158435750565b61406a906040519182917fff828faa00000000000000000000000000000000000000000000000000000000835260206004840181815201906105bd565b6040517fff828faa000000000000000000000000000000000000000000000000000000008152602060048201528061406a60248201856105bd565b80548210156127fd5760005260206000200190600090565b916158ed918354906000199060031b92831b921b19161790565b9055565b8054801561591957600019019061590882826158bb565b60001982549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60018101918060005282602052604060002054928315156000146159fa5760001984018481116126a65783549360001985019485116126a65760009585836159ab9761599c95036159b1575b5050506158f1565b90600052602052604060002090565b55600190565b6159e16159db916159d26159c86159f195886158bb565b90549060031b1c90565b928391876158bb565b906158d3565b8590600052602052604060002090565b55388080615994565b50505050600090565b805490680100000000000000008210156105225781615a2a9160016158ed940181556158bb565b81939154906000199060031b92831b921b19161790565b600081815260036020526040902054615a7657615a5f816002615a03565b600254906000526003602052604060002055600190565b50600090565b6000828152600182016020526040902054615ab35780615a9e83600193615a03565b80549260005201602052604060002055600190565b5050600090565b600081815260036020526040902054908115615ab3576000198201908282116126a6576002549260001984019384116126a65783836159ab9460009603615b1a575b505050615b0960026158f1565b600390600052602052604060002090565b615b096159db91615b326159c8615b3c9560026158bb565b92839160026158bb565b55388080615afc56fea164736f6c634300081a000a",
}
var FeeQuoterABI = FeeQuoterMetaData.ABI
diff --git a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go
index 8d3c36757aa..8f7b15cd5e4 100644
--- a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go
+++ b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go
@@ -44,8 +44,8 @@ type ClientEVMTokenAmount struct {
}
var MaybeRevertMessageReceiverMetaData = &bind.MetaData{
- ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"s_toRevert\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setErr\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRevert\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"event\",\"name\":\"MessageReceived\",\"inputs\":[],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValueReceived\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CustomError\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"ReceiveRevert\",\"inputs\":[]}]",
- Bin: "0x608034607d57601f6107a838819003918201601f19168301916001600160401b03831184841017608257808492602094604052833981010312607d5751801515809103607d57600080546001600160a81b0319163360ff60a01b19161760a09290921b60ff60a01b1691909117905560405161070f90816100998239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561007e575b50361561001b57600080fd5b60ff60005460a01c16610054577fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef6020604051348152a1005b7f3085b8db0000000000000000000000000000000000000000000000000000000060005260046000fd5b60003560e01c90816301ffc9a7146105f3575080635100fc21146105af57806377f5b0e6146102da57806385572ffb1461014d57638fb5f171146100c2573861000f565b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435801515809103610148577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006000549260a01b16911617600055600080f35b600080fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a091360301126101485760ff60005460a01c166101ee577fd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e8600080a1005b6040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526020600482015280600060015461022a816106af565b908160248501526001811690816000146102a2575060011461024b57500390fd5b6001600090815291507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061028857505081010360440190fd5b805460448487010152849350602090920191600101610276565b604493507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201010390fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148573660238201121561014857806004013567ffffffffffffffff811161058057604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8501160116830183811067ffffffffffffffff82111761058057604052818352366024838301011161014857816000926024602093018386013783010152805167ffffffffffffffff8111610580576103be6001546106af565b601f81116104dd575b50602091601f821160011461042357918192600092610418575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c191617600155600080f35b0151905082806103e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169260016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69160005b8581106104c55750836001951061048e575b505050811b01600155005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055828080610483565b91926020600181928685015181550194019201610471565b6001600052601f820160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6019060208310610558575b601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601905b81811061054c57506103c7565b6000815560010161053f565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69150610515565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101485760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857602060ff60005460a01c166040519015158152f35b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361014857817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115610685575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361067e565b90600182811c921680156106f8575b60208310146106c957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916106be56fea164736f6c634300081a000a",
+ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"balanceOfToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ccipReceive\",\"inputs\":[{\"name\":\"message\",\"type\":\"tuple\",\"internalType\":\"structClient.Any2EVMMessage\",\"components\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"s_toRevert\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setErr\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRevert\",\"inputs\":[{\"name\":\"toRevert\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawTokens\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"MessageReceived\",\"inputs\":[{\"name\":\"messageId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"sourceChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"sender\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\",\"indexed\":false,\"internalType\":\"structClient.EVMTokenAmount[]\",\"components\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NativeFundsWithdrawn\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensWithdrawn\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ValueReceived\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CustomError\",\"inputs\":[{\"name\":\"err\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InsufficientBalance\",\"inputs\":[{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"required\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ReceiveRevert\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]",
+ Bin: "0x60a034607657601f610dbb38819003918201601f19168301916001600160401b03831184841017607b57808492602094604052833981010312607657518015158091036076573360805260ff801960005416911617600055604051610d29908161009282396080518181816107e301526109300152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561007b575b50361561001b57600080fd5b60ff60005416610051577fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef6020604051348152a1005b7f3085b8db0000000000000000000000000000000000000000000000000000000060005260046000fd5b60003560e01c90816301ffc9a714610adf5750806306b091f9146108df57806324600fc3146107b25780635100fc211461077157806377f5b0e6146104db57806385572ffb1461022e5780638fb5f171146101c05763b99152d0146100e0573861000f565b346101a75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a7576024602073ffffffffffffffffffffffffffffffffffffffff610130610b9b565b16604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa80156101b45760009061017c575b602090604051908152f35b506020813d6020116101ac575b8161019660209383610bbe565b810103126101a75760209051610171565b600080fd5b3d9150610189565b6040513d6000823e3d90fd5b346101a75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a7576004358015158091036101a75760ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005416911617600055600080f35b346101a75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a75760043567ffffffffffffffff81116101a7578060040181360360a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101a75760ff600054166103ef5760248301359267ffffffffffffffff84168094036101a7576102cf6044820184610c8c565b90916102de6064820186610c8c565b9490917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd608482013592018212156101a757019360048501359467ffffffffffffffff86116101a757602401968560061b360388136101a75760209461036c9461035e9260405199358a52878a015260a060408a015260a0890191610cdd565b918683036060880152610cdd565b83810360808501528281520192906000905b8082106103ad577f707732b700184c0ab3b799f43f03de9b3606a144cfb367f98291044e71972cdc84860385a1005b90919384359073ffffffffffffffffffffffffffffffffffffffff82168092036101a7576040816001938293526020880135602082015201950192019061037e565b6040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526020600482015280600060015461042b81610c39565b908160248501526001811690816000146104a3575060011461044c57500390fd5b6001600090815291507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061048957505081010360440190fd5b805460448487010152849350602090920191600101610477565b604493507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201010390fd5b346101a75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a75760043567ffffffffffffffff81116101a757366023820112156101a757806004013561053581610bff565b916105436040519384610bbe565b81835236602483830101116101a757816000926024602093018386013783010152805167ffffffffffffffff811161074257610580600154610c39565b601f811161069f575b50602091601f82116001146105e5579181926000926105da575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c191617600155600080f35b0151905082806105a3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169260016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69160005b85811061068757508360019510610650575b505050811b01600155005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055828080610645565b91926020600181928685015181550194019201610633565b6001600052601f820160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601906020831061071a575b601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601905b81811061070e5750610589565b60008155600101610701565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf691506106d7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101a75760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a757602060ff600054166040519015158152f35b346101a75760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a7577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8116908133036108b55760008080804780955af13d156108b0573d61083b81610bff565b906108496040519283610bbe565b8152600060203d92013e5b156108865760207fd50b71a2790ecccf5881141fe9ae079e17c66aace5d50ba383d443ecd398ffa591604051908152a2005b7f90b8ec180000000000000000000000000000000000000000000000000000000060005260046000fd5b610854565b7f82b429000000000000000000000000000000000000000000000000000000000060005260046000fd5b346101a75760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a757610916610b9b565b60243573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016918233036108b55773ffffffffffffffffffffffffffffffffffffffff16906040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa9081156101b457600091610aad575b50818110610a7d57506040517fa9059cbb0000000000000000000000000000000000000000000000000000000081528360048201528160248201526020816044816000875af19081156101b457600091610a3b575b50156108865760207f6337ed398c0e8467698c581374fdce4db14922df487b5a39483079f5f59b60a491604051908152a3005b6020813d602011610a75575b81610a5460209383610bbe565b81010312610a715751908115158203610a6e575084610a08565b80fd5b5080fd5b3d9150610a47565b7fcf4791810000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b906020823d602011610ad7575b81610ac760209383610bbe565b81010312610a6e575051846109b3565b3d9150610aba565b346101a75760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a757600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101a757817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115610b71575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610b6a565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101a757565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761074257604052565b67ffffffffffffffff811161074257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b90600182811c92168015610c82575b6020831014610c5357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691610c48565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101a7570180359067ffffffffffffffff82116101a7576020019181360383136101a757565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601376000858286010152011601019056fea164736f6c634300081a000a",
}
var MaybeRevertMessageReceiverABI = MaybeRevertMessageReceiverMetaData.ABI
@@ -184,6 +184,28 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorRaw) Tran
return _MaybeRevertMessageReceiver.Contract.contract.Transact(opts, method, params...)
}
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverCaller) BalanceOfToken(opts *bind.CallOpts, token common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _MaybeRevertMessageReceiver.contract.Call(opts, &out, "balanceOfToken", token)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverSession) BalanceOfToken(token common.Address) (*big.Int, error) {
+ return _MaybeRevertMessageReceiver.Contract.BalanceOfToken(&_MaybeRevertMessageReceiver.CallOpts, token)
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverCallerSession) BalanceOfToken(token common.Address) (*big.Int, error) {
+ return _MaybeRevertMessageReceiver.Contract.BalanceOfToken(&_MaybeRevertMessageReceiver.CallOpts, token)
+}
+
func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverCaller) SToRevert(opts *bind.CallOpts) (bool, error) {
var out []interface{}
err := _MaybeRevertMessageReceiver.contract.Call(opts, &out, "s_toRevert")
@@ -228,16 +250,16 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverCallerSession) Supp
return _MaybeRevertMessageReceiver.Contract.SupportsInterface(&_MaybeRevertMessageReceiver.CallOpts, interfaceId)
}
-func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) CcipReceive(opts *bind.TransactOpts, arg0 ClientAny2EVMMessage) (*types.Transaction, error) {
- return _MaybeRevertMessageReceiver.contract.Transact(opts, "ccipReceive", arg0)
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) CcipReceive(opts *bind.TransactOpts, message ClientAny2EVMMessage) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.contract.Transact(opts, "ccipReceive", message)
}
-func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverSession) CcipReceive(arg0 ClientAny2EVMMessage) (*types.Transaction, error) {
- return _MaybeRevertMessageReceiver.Contract.CcipReceive(&_MaybeRevertMessageReceiver.TransactOpts, arg0)
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverSession) CcipReceive(message ClientAny2EVMMessage) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.CcipReceive(&_MaybeRevertMessageReceiver.TransactOpts, message)
}
-func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorSession) CcipReceive(arg0 ClientAny2EVMMessage) (*types.Transaction, error) {
- return _MaybeRevertMessageReceiver.Contract.CcipReceive(&_MaybeRevertMessageReceiver.TransactOpts, arg0)
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorSession) CcipReceive(message ClientAny2EVMMessage) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.CcipReceive(&_MaybeRevertMessageReceiver.TransactOpts, message)
}
func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) SetErr(opts *bind.TransactOpts, err []byte) (*types.Transaction, error) {
@@ -264,6 +286,30 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorSession)
return _MaybeRevertMessageReceiver.Contract.SetRevert(&_MaybeRevertMessageReceiver.TransactOpts, toRevert)
}
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) WithdrawFunds(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.contract.Transact(opts, "withdrawFunds")
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverSession) WithdrawFunds() (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.WithdrawFunds(&_MaybeRevertMessageReceiver.TransactOpts)
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorSession) WithdrawFunds() (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.WithdrawFunds(&_MaybeRevertMessageReceiver.TransactOpts)
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) WithdrawTokens(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.contract.Transact(opts, "withdrawTokens", token, amount)
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverSession) WithdrawTokens(token common.Address, amount *big.Int) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.WithdrawTokens(&_MaybeRevertMessageReceiver.TransactOpts, token, amount)
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactorSession) WithdrawTokens(token common.Address, amount *big.Int) (*types.Transaction, error) {
+ return _MaybeRevertMessageReceiver.Contract.WithdrawTokens(&_MaybeRevertMessageReceiver.TransactOpts, token, amount)
+}
+
func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
return _MaybeRevertMessageReceiver.contract.RawTransact(opts, nil)
}
@@ -337,7 +383,12 @@ func (it *MaybeRevertMessageReceiverMessageReceivedIterator) Close() error {
}
type MaybeRevertMessageReceiverMessageReceived struct {
- Raw types.Log
+ MessageId [32]byte
+ SourceChainSelector uint64
+ Sender []byte
+ Data []byte
+ DestTokenAmounts []ClientEVMTokenAmount
+ Raw types.Log
}
func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) FilterMessageReceived(opts *bind.FilterOpts) (*MaybeRevertMessageReceiverMessageReceivedIterator, error) {
@@ -392,6 +443,271 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) ParseMess
return event, nil
}
+type MaybeRevertMessageReceiverNativeFundsWithdrawnIterator struct {
+ Event *MaybeRevertMessageReceiverNativeFundsWithdrawn
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *MaybeRevertMessageReceiverNativeFundsWithdrawnIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(MaybeRevertMessageReceiverNativeFundsWithdrawn)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(MaybeRevertMessageReceiverNativeFundsWithdrawn)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *MaybeRevertMessageReceiverNativeFundsWithdrawnIterator) Error() error {
+ return it.fail
+}
+
+func (it *MaybeRevertMessageReceiverNativeFundsWithdrawnIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type MaybeRevertMessageReceiverNativeFundsWithdrawn struct {
+ Owner common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) FilterNativeFundsWithdrawn(opts *bind.FilterOpts, owner []common.Address) (*MaybeRevertMessageReceiverNativeFundsWithdrawnIterator, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+
+ logs, sub, err := _MaybeRevertMessageReceiver.contract.FilterLogs(opts, "NativeFundsWithdrawn", ownerRule)
+ if err != nil {
+ return nil, err
+ }
+ return &MaybeRevertMessageReceiverNativeFundsWithdrawnIterator{contract: _MaybeRevertMessageReceiver.contract, event: "NativeFundsWithdrawn", logs: logs, sub: sub}, nil
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) WatchNativeFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *MaybeRevertMessageReceiverNativeFundsWithdrawn, owner []common.Address) (event.Subscription, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+
+ logs, sub, err := _MaybeRevertMessageReceiver.contract.WatchLogs(opts, "NativeFundsWithdrawn", ownerRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(MaybeRevertMessageReceiverNativeFundsWithdrawn)
+ if err := _MaybeRevertMessageReceiver.contract.UnpackLog(event, "NativeFundsWithdrawn", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) ParseNativeFundsWithdrawn(log types.Log) (*MaybeRevertMessageReceiverNativeFundsWithdrawn, error) {
+ event := new(MaybeRevertMessageReceiverNativeFundsWithdrawn)
+ if err := _MaybeRevertMessageReceiver.contract.UnpackLog(event, "NativeFundsWithdrawn", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type MaybeRevertMessageReceiverTokensWithdrawnIterator struct {
+ Event *MaybeRevertMessageReceiverTokensWithdrawn
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *MaybeRevertMessageReceiverTokensWithdrawnIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(MaybeRevertMessageReceiverTokensWithdrawn)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(MaybeRevertMessageReceiverTokensWithdrawn)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *MaybeRevertMessageReceiverTokensWithdrawnIterator) Error() error {
+ return it.fail
+}
+
+func (it *MaybeRevertMessageReceiverTokensWithdrawnIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type MaybeRevertMessageReceiverTokensWithdrawn struct {
+ Token common.Address
+ Owner common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) FilterTokensWithdrawn(opts *bind.FilterOpts, token []common.Address, owner []common.Address) (*MaybeRevertMessageReceiverTokensWithdrawnIterator, error) {
+
+ var tokenRule []interface{}
+ for _, tokenItem := range token {
+ tokenRule = append(tokenRule, tokenItem)
+ }
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+
+ logs, sub, err := _MaybeRevertMessageReceiver.contract.FilterLogs(opts, "TokensWithdrawn", tokenRule, ownerRule)
+ if err != nil {
+ return nil, err
+ }
+ return &MaybeRevertMessageReceiverTokensWithdrawnIterator{contract: _MaybeRevertMessageReceiver.contract, event: "TokensWithdrawn", logs: logs, sub: sub}, nil
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) WatchTokensWithdrawn(opts *bind.WatchOpts, sink chan<- *MaybeRevertMessageReceiverTokensWithdrawn, token []common.Address, owner []common.Address) (event.Subscription, error) {
+
+ var tokenRule []interface{}
+ for _, tokenItem := range token {
+ tokenRule = append(tokenRule, tokenItem)
+ }
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+
+ logs, sub, err := _MaybeRevertMessageReceiver.contract.WatchLogs(opts, "TokensWithdrawn", tokenRule, ownerRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(MaybeRevertMessageReceiverTokensWithdrawn)
+ if err := _MaybeRevertMessageReceiver.contract.UnpackLog(event, "TokensWithdrawn", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiverFilterer) ParseTokensWithdrawn(log types.Log) (*MaybeRevertMessageReceiverTokensWithdrawn, error) {
+ event := new(MaybeRevertMessageReceiverTokensWithdrawn)
+ if err := _MaybeRevertMessageReceiver.contract.UnpackLog(event, "TokensWithdrawn", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
type MaybeRevertMessageReceiverValueReceivedIterator struct {
Event *MaybeRevertMessageReceiverValueReceived
@@ -513,6 +829,10 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiver) ParseLog(log type
switch log.Topics[0] {
case _MaybeRevertMessageReceiver.abi.Events["MessageReceived"].ID:
return _MaybeRevertMessageReceiver.ParseMessageReceived(log)
+ case _MaybeRevertMessageReceiver.abi.Events["NativeFundsWithdrawn"].ID:
+ return _MaybeRevertMessageReceiver.ParseNativeFundsWithdrawn(log)
+ case _MaybeRevertMessageReceiver.abi.Events["TokensWithdrawn"].ID:
+ return _MaybeRevertMessageReceiver.ParseTokensWithdrawn(log)
case _MaybeRevertMessageReceiver.abi.Events["ValueReceived"].ID:
return _MaybeRevertMessageReceiver.ParseValueReceived(log)
@@ -522,7 +842,15 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiver) ParseLog(log type
}
func (MaybeRevertMessageReceiverMessageReceived) Topic() common.Hash {
- return common.HexToHash("0xd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e8")
+ return common.HexToHash("0x707732b700184c0ab3b799f43f03de9b3606a144cfb367f98291044e71972cdc")
+}
+
+func (MaybeRevertMessageReceiverNativeFundsWithdrawn) Topic() common.Hash {
+ return common.HexToHash("0xd50b71a2790ecccf5881141fe9ae079e17c66aace5d50ba383d443ecd398ffa5")
+}
+
+func (MaybeRevertMessageReceiverTokensWithdrawn) Topic() common.Hash {
+ return common.HexToHash("0x6337ed398c0e8467698c581374fdce4db14922df487b5a39483079f5f59b60a4")
}
func (MaybeRevertMessageReceiverValueReceived) Topic() common.Hash {
@@ -534,16 +862,22 @@ func (_MaybeRevertMessageReceiver *MaybeRevertMessageReceiver) Address() common.
}
type MaybeRevertMessageReceiverInterface interface {
+ BalanceOfToken(opts *bind.CallOpts, token common.Address) (*big.Int, error)
+
SToRevert(opts *bind.CallOpts) (bool, error)
SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error)
- CcipReceive(opts *bind.TransactOpts, arg0 ClientAny2EVMMessage) (*types.Transaction, error)
+ CcipReceive(opts *bind.TransactOpts, message ClientAny2EVMMessage) (*types.Transaction, error)
SetErr(opts *bind.TransactOpts, err []byte) (*types.Transaction, error)
SetRevert(opts *bind.TransactOpts, toRevert bool) (*types.Transaction, error)
+ WithdrawFunds(opts *bind.TransactOpts) (*types.Transaction, error)
+
+ WithdrawTokens(opts *bind.TransactOpts, token common.Address, amount *big.Int) (*types.Transaction, error)
+
Receive(opts *bind.TransactOpts) (*types.Transaction, error)
FilterMessageReceived(opts *bind.FilterOpts) (*MaybeRevertMessageReceiverMessageReceivedIterator, error)
@@ -552,6 +886,18 @@ type MaybeRevertMessageReceiverInterface interface {
ParseMessageReceived(log types.Log) (*MaybeRevertMessageReceiverMessageReceived, error)
+ FilterNativeFundsWithdrawn(opts *bind.FilterOpts, owner []common.Address) (*MaybeRevertMessageReceiverNativeFundsWithdrawnIterator, error)
+
+ WatchNativeFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *MaybeRevertMessageReceiverNativeFundsWithdrawn, owner []common.Address) (event.Subscription, error)
+
+ ParseNativeFundsWithdrawn(log types.Log) (*MaybeRevertMessageReceiverNativeFundsWithdrawn, error)
+
+ FilterTokensWithdrawn(opts *bind.FilterOpts, token []common.Address, owner []common.Address) (*MaybeRevertMessageReceiverTokensWithdrawnIterator, error)
+
+ WatchTokensWithdrawn(opts *bind.WatchOpts, sink chan<- *MaybeRevertMessageReceiverTokensWithdrawn, token []common.Address, owner []common.Address) (event.Subscription, error)
+
+ ParseTokensWithdrawn(log types.Log) (*MaybeRevertMessageReceiverTokensWithdrawn, error)
+
FilterValueReceived(opts *bind.FilterOpts) (*MaybeRevertMessageReceiverValueReceivedIterator, error)
WatchValueReceived(opts *bind.WatchOpts, sink chan<- *MaybeRevertMessageReceiverValueReceived) (event.Subscription, error)
diff --git a/core/gethwrappers/ccip/generated/siloed_lock_release_token_pool/siloed_lock_release_token_pool.go b/core/gethwrappers/ccip/generated/siloed_lock_release_token_pool/siloed_lock_release_token_pool.go
new file mode 100644
index 00000000000..b69ab8d64dc
--- /dev/null
+++ b/core/gethwrappers/ccip/generated/siloed_lock_release_token_pool/siloed_lock_release_token_pool.go
@@ -0,0 +1,4197 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package siloed_lock_release_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 SiloedLockReleaseTokenPoolSiloConfigUpdate struct {
+ RemoteChainSelector uint64
+ Rebalancer common.Address
+}
+
+type TokenPoolChainUpdate struct {
+ RemoteChainSelector uint64
+ RemotePoolAddresses [][]byte
+ RemoteTokenAddress []byte
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+}
+
+var SiloedLockReleaseTokenPoolMetaData = &bind.MetaData{
+ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"},{\"name\":\"localTokenDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"allowlist\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"acceptOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyAllowListUpdates\",\"inputs\":[{\"name\":\"removes\",\"type\":\"address[]\",\"internalType\":\"address[]\"},{\"name\":\"adds\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"applyChainUpdates\",\"inputs\":[{\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"chainsToAdd\",\"type\":\"tuple[]\",\"internalType\":\"structTokenPool.ChainUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"},{\"name\":\"remoteTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getAllowList\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAllowListEnabled\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getAvailableTokens\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"lockedTokens\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentInboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentOutboundRateLimiterState\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.TokenBucket\",\"components\":[{\"name\":\"tokens\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"lastUpdated\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRateLimitAdmin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRebalancer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemotePools\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRemoteToken\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRmnProxy\",\"inputs\":[],\"outputs\":[{\"name\":\"rmnProxy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRouter\",\"inputs\":[],\"outputs\":[{\"name\":\"router\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSiloRebalancer\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSupportedChains\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getToken\",\"inputs\":[],\"outputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTokenDecimals\",\"inputs\":[],\"outputs\":[{\"name\":\"decimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getUnsiloedLiquidity\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSiloed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isSupportedToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lockOrBurn\",\"inputs\":[{\"name\":\"lockOrBurnIn\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnInV1\",\"components\":[{\"name\":\"receiver\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"originalSender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.LockOrBurnOutV1\",\"components\":[{\"name\":\"destTokenAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"destPoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"provideLiquidity\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"provideSiloedLiquidity\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"releaseOrMint\",\"inputs\":[{\"name\":\"releaseOrMintIn\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintInV1\",\"components\":[{\"name\":\"originalSender\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"localToken\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"offchainTokenData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"components\":[{\"name\":\"destinationAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeRemotePool\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfig\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"outboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setChainRateLimiterConfigs\",\"inputs\":[{\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"outboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundConfigs\",\"type\":\"tuple[]\",\"internalType\":\"structRateLimiter.Config[]\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRateLimitAdmin\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRebalancer\",\"inputs\":[{\"name\":\"newRebalancer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRouter\",\"inputs\":[{\"name\":\"newRouter\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setSiloRebalancer\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"newRebalancer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"typeAndVersion\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateSiloDesignations\",\"inputs\":[{\"name\":\"removes\",\"type\":\"uint64[]\",\"internalType\":\"uint64[]\"},{\"name\":\"adds\",\"type\":\"tuple[]\",\"internalType\":\"structSiloedLockReleaseTokenPool.SiloConfigUpdate[]\",\"components\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"rebalancer\",\"type\":\"address\",\"internalType\":\"address\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawLiquidity\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawSiloedLiquidity\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"AllowListAdd\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AllowListRemove\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burned\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remoteToken\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainConfigured\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]},{\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainSiloed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"rebalancer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChainUnsiloed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"amountUnsiloed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ConfigChanged\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LiquidityAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"provider\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"LiquidityRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"},{\"name\":\"remover\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Locked\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Minted\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferRequested\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RateLimitAdminSet\",\"inputs\":[{\"name\":\"rateLimitAdmin\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Released\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemotePoolRemoved\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RouterUpdated\",\"inputs\":[{\"name\":\"oldRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRouter\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SiloRebalancerSet\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"indexed\":true,\"internalType\":\"uint64\"},{\"name\":\"oldRebalancer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRebalancer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TokensConsumed\",\"inputs\":[{\"name\":\"tokens\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UnsiloedRebalancerSet\",\"inputs\":[{\"name\":\"oldRebalancer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRebalancer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AggregateValueMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AggregateValueRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"AllowListNotEnabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BucketOverfilled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CallerIsNotARampOnRouter\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"CannotTransferToSelf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChainAlreadyExists\",\"inputs\":[{\"name\":\"chainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotAllowed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"ChainNotSiloed\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"CursedByRMN\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DisabledNonZeroRateLimit\",\"inputs\":[{\"name\":\"config\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InsufficientLiquidity\",\"inputs\":[{\"name\":\"availableLiquidity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requestedAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidChainSelector\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"InvalidDecimalArgs\",\"inputs\":[{\"name\":\"expected\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"actual\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"InvalidRateLimitRate\",\"inputs\":[{\"name\":\"rateLimiterConfig\",\"type\":\"tuple\",\"internalType\":\"structRateLimiter.Config\",\"components\":[{\"name\":\"isEnabled\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"capacity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"rate\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}]},{\"type\":\"error\",\"name\":\"InvalidRemoteChainDecimals\",\"inputs\":[{\"name\":\"sourcePoolData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidRemotePoolForChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidSourcePoolAddress\",\"inputs\":[{\"name\":\"sourcePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"LiquidityAmountCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MismatchedArrayLengths\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MustBeProposedOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NonExistentChain\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"}]},{\"type\":\"error\",\"name\":\"OnlyCallableByOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OverflowDetected\",\"inputs\":[{\"name\":\"remoteDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"localDecimals\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"remoteAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnerCannotBeZero\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PoolAlreadyAdded\",\"inputs\":[{\"name\":\"remoteChainSelector\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"remotePoolAddress\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"RateLimitMustBeDisabled\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"SenderNotAllowed\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenMaxCapacityExceeded\",\"inputs\":[{\"name\":\"capacity\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requested\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"TokenRateLimitReached\",\"inputs\":[{\"name\":\"minWaitInSeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokenAddress\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"caller\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ZeroAddressNotAllowed\",\"inputs\":[]}]",
+ Bin: "0x61010080604052346103775761550d803803809161001d82856103f6565b833981019060a0818303126103775780516001600160a01b038116918282036103775761004c60208201610419565b60408201519092906001600160401b0381116103775782019480601f87011215610377578551956001600160401b0387116103e0578660051b906020820197610098604051998a6103f6565b885260208089019282010192831161037757602001905b8282106103c8575050506100d160806100ca60608501610427565b9301610427565b9333156103b757600180546001600160a01b03191633179055801580156103a6575b8015610395575b6103845760049260209260805260c0526040519283809263313ce56760e01b82525afa60009181610343575b50610318575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526101fa575b604051614f3190816105dc82396080518181816103e4015281816110950152818161187401528181611a6e0152818161295a01528181612b3801528181612f1a01528181612f7401526130dc015260a051818181611b2e01528181612ec301528181613b0c0152613b8f015260c051818181610df90152818161190f01526129f6015260e051818181610da701528181611953015261275b0152f35b604051602061020981836103f6565b60008252600036813760e051156103075760005b8251811015610284576001906001600160a01b0361023b828661043b565b5116836102478261047d565b610254575b50500161021d565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1388361024c565b50905060005b82518110156102fe576001906001600160a01b036102a8828661043b565b511680156102f857836102ba8261057b565b6102c8575b50505b0161028a565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102bf565b506102c2565b5050503861015e565b6335f4a7b360e01b60005260046000fd5b60ff1660ff821681810361032c575061012c565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d60201161037c575b8161035f602093836103f6565b810103126103775761037090610419565b9038610126565b600080fd5b3d9150610352565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038316156100fa565b506001600160a01b038516156100f3565b639b15e16f60e01b60005260046000fd5b602080916103d584610427565b8152019101906100af565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103e057604052565b519060ff8216820361037757565b51906001600160a01b038216820361037757565b805182101561044f5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561044f5760005260206000200190600090565b600081815260036020526040902054801561057457600019810181811161055e5760025460001981019190821161055e5781810361050d575b50505060025480156104f757600019016104d1816002610465565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61054661051e61052f936002610465565b90549060031b1c9283926002610465565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104b6565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105d557600254680100000000000000008110156103e0576105bc61052f8260018594016002556002610465565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a714613152575080630a861f2a1461301e578063181f5a7714612f9857806321df0da714612f47578063240028e814612ee757806324f65ee714612ea95780632d4a148f14612d6d57806331238ffc14612d2757806339077537146128f0578063432a6ba3146128bc5780634c5ef0ed146128a357806354c8a4f31461272957806362ddd3c4146126a65780636600f92c1461258a5780636cfd1553146124d05780636d3d1a581461249c5780636d9d216c146120cc57806379ba5097146120015780637d54534e14611f745780638926f54f14611f2f5780638da5cb5b14611efb578063962d402014611da55780639a4575b914611809578063a42a7b8b1461169b578063a7cd63b7146115e7578063acfecf91146114c7578063af0e58b9146114a9578063af58d59f1461145f578063b0f479a11461142b578063b7946580146113f3578063c0d786551461130b578063c4bffe2b146111db578063c75eea9c14611132578063ce3c752814610fd5578063cf7401f314610e5e578063d70be92f14610e1d578063dc0bd97114610dcc578063e0351e1314610d8f578063e8a1da17146104aa578063eb521a4c146102ef578063f1e73399146102c45763f2fde38b146101ed57600080fd5b346102bf5760206003193601126102bf5773ffffffffffffffffffffffffffffffffffffffff61021b61339a565b610223613cfb565b1633811461029557807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346102bf5760206003193601126102bf5760206102e76102e26133bd565b613a43565b604051908152f35b346102bf5760206003193601126102bf5760043580156104805773ffffffffffffffffffffffffffffffffffffffff61032860006139a2565b1633036104525760008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e9547f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e89060a01c60ff161561043d5761039282825461375a565b90555b6104086040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152826064820152606481526103e26084826132c0565b7f0000000000000000000000000000000000000000000000000000000000000000614296565b604051906000825260208201527f569a440e6842b5e5a7ac02286311855f5a0b81b9390909e552e82aaf02c9e9bf60403392a2005b5061044a81600a5461375a565b600a55610395565b7f8e4a23d6000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b7fa90c0d190000000000000000000000000000000000000000000000000000000060005260046000fd5b346102bf576104b83661346a565b9190926104c3613cfb565b6000905b828210610be65750505060009063ffffffff4216907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee184360301925b81811015610be4576000918160051b86013585811215610be05786019061012082360312610be05760405195610538876132a4565b823567ffffffffffffffff81168103610bdc578752602083013567ffffffffffffffff8111610bdc5783019536601f88011215610bdc5786359661057b8861369b565b97610589604051998a6132c0565b8089526020808a019160051b83010190368211610bd85760208301905b828210610ba5575050505060208801968752604084013567ffffffffffffffff8111610ba1576105d99036908601613a28565b92604089019384526106036105f1366060880161350a565b9560608b0196875260c036910161350a565b9660808a01978852610615865161413b565b61061f885161413b565b84515115610b795761063b67ffffffffffffffff8b5116614ac1565b15610b425767ffffffffffffffff8a5116815260076020526040812061077b87516fffffffffffffffffffffffffffffffff604082015116906107366fffffffffffffffffffffffffffffffff602083015116915115158360806040516106a1816132a4565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b6108a189516fffffffffffffffffffffffffffffffff6040820151169061085c6fffffffffffffffffffffffffffffffff602083015116915115158360806040516107c5816132a4565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b6004865191019080519067ffffffffffffffff8211610b15576108c4835461379b565b601f8111610ada575b50602090601f8311600114610a3b5761091b9291859183610a30575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b88518051821015610953579061094d6001926109468367ffffffffffffffff8f511692613787565b5190613d46565b0161091e565b5050977f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2939199975095610a2167ffffffffffffffff60019796949851169251935191516109ed6109b86040519687968752610100602088015261010087019061333b565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a101939193929092610503565b015190508f806108e9565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b818110610ac25750908460019594939210610a8b575b505050811b01905561091e565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080610a7e565b92936020600181928786015181550195019301610a68565b610b059084865260208620601f850160051c81019160208610610b0b575b601f0160051c01906139fe565b8e6108cd565b9091508190610af8565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff8111610bd457602091610bc98392833691890101613a28565b8152019101906105a6565b8a80fd5b8880fd5b8580fd5b8380fd5b005b909267ffffffffffffffff610c07610c0286868699979961371b565b6135de565b1692610c1284614802565b15610d6157836000526007602052610c306005604060002001614609565b9260005b8451811015610c6c57600190866000526007602052610c656005604060002001610c5e8389613787565b519061492d565b5001610c34565b5093909491959250806000526007602052600560406000206000815560006001820155600060028201556000600382015560048101610cab815461379b565b9081610d1e575b5050018054906000815581610cfd575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a10190919392936104c7565b6000526020600020908101905b81811015610cc25760008155600101610d0a565b81601f60009311600114610d365750555b8880610cb2565b81835260208320610d5191601f01861c8101906001016139fe565b8082528160208120915555610d2f565b837f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102bf5760006003193601126102bf5760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b346102bf5760006003193601126102bf57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102bf5760206003193601126102bf576020610e40610e3b6133bd565b6139a2565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b346102bf5760e06003193601126102bf57610e776133bd565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102bf57604051610ead8161326c565b60243580151581036102bf5781526044356fffffffffffffffffffffffffffffffff811681036102bf5760208201526064356fffffffffffffffffffffffffffffffff811681036102bf57604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c3601126102bf5760405190610f348261326c565b60843580151581036102bf57825260a4356fffffffffffffffffffffffffffffffff811681036102bf57602083015260c4356fffffffffffffffffffffffffffffffff811681036102bf57604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610fb3575b61045257610be492613f86565b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610fa6565b346102bf5760406003193601126102bf57610fee6133bd565b60243580156104805773ffffffffffffffffffffffffffffffffffffffff611015836139a2565b1633036104525767ffffffffffffffff8216600052600c602052604060002060ff600182015460a01c168060001461112a5781545b8084116110f85750916110de917f58fca2457646a9f47422ab9eb9bff90cef88cd8b8725ab52b1d17baa392d784e936000146110e35761108b8282546135f3565b90555b6110b981337f0000000000000000000000000000000000000000000000000000000000000000613c99565b6040519182913395836020909392919367ffffffffffffffff60408201951681520152565b0390a2005b506110f081600a546135f3565b600a5561108e565b83907fa17e11d50000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b600a5461104a565b346102bf5760206003193601126102bf5767ffffffffffffffff6111546133bd565b61115c6138ef565b501660005260076020526111d761117e611179604060002061391a565b6140b6565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b346102bf5760006003193601126102bf576040516005548082528160208101600560005260206000209260005b8181106112f257505061121d925003826132c0565b80519061124261122c8361369b565b9261123a60405194856132c0565b80845261369b565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401920136833760005b81518110156112a2578067ffffffffffffffff61128f60019385613787565b511661129b8287613787565b5201611270565b5050906040519182916020830190602084525180915260408301919060005b8181106112cf575050500390f35b825167ffffffffffffffff168452859450602093840193909201916001016112c1565b8454835260019485019486945060209093019201611208565b346102bf5760206003193601126102bf5761132461339a565b61132c613cfb565b73ffffffffffffffffffffffffffffffffffffffff81169081156113c957600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000811690931790556040805173ffffffffffffffffffffffffffffffffffffffff93841681529190921660208201527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491819081015b0390a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b346102bf5760206003193601126102bf576111d76114176114126133bd565b613980565b60405191829160208352602083019061333b565b346102bf5760006003193601126102bf57602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b346102bf5760206003193601126102bf5767ffffffffffffffff6114816133bd565b6114896138ef565b501660005260076020526111d761117e611179600260406000200161391a565b346102bf5760006003193601126102bf576020600a54604051908152f35b346102bf5767ffffffffffffffff6114de366133d4565b9290916114e9613cfb565b1690611502826000526006602052604060002054151590565b156115b95781600052600760205261153360056040600020016115263686856135a7565b602081519101209061492d565b15611572577f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691926110de6040519283926020845260208401916138b0565b6115b5906040519384937f74f23c7c00000000000000000000000000000000000000000000000000000000855260048501526040602485015260448401916138b0565b0390fd5b507f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102bf5760006003193601126102bf5760405160025490818152602081018092600260005260206000209060005b818110611685575050508161162c9103826132c0565b6040519182916020830190602084525180915260408301919060005b818110611656575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611648565b8254845260209093019260019283019201611616565b346102bf5760206003193601126102bf5767ffffffffffffffff6116bd6133bd565b1660005260076020526116d66005604060002001614609565b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061171c6117068461369b565b9361171460405195866132c0565b80855261369b565b0160005b8181106117f857505060005b8151811015611774578061174260019284613787565b51600052600860205261175860406000206137ee565b6117628286613787565b5261176d8185613787565b500161172c565b826040518091602082016020835281518091526040830190602060408260051b8601019301916000905b8282106117ad57505050500390f35b919360206117e8827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06001959799849503018652885161333b565b960192019201859493919261179e565b806060602080938701015201611720565b346102bf5760206003193601126102bf5760043567ffffffffffffffff81116102bf5760a060031982360301126102bf576060602060405161184a81613288565b82815201526084810161185c8161362f565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611d5957506024810177ffffffffffffffff000000000000000000000000000000006118c2826135de565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611c7157600091611d2a575b50611d00576119516044830161362f565b7f0000000000000000000000000000000000000000000000000000000000000000611caa575b5067ffffffffffffffff61198a826135de565b166119a2816000526006602052604060002054151590565b15611c7d57602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa908115611c7157600091611c07575b5073ffffffffffffffffffffffffffffffffffffffff163303611bd95761141281611b949367ffffffffffffffff6064611a41611b24966135de565b92013591166000526007602052611a9460406000208273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614b70565b67ffffffffffffffff611aa6836135de565b16600052600c60205260ff60016040600020015460a01c16600014611bc55767ffffffffffffffff611ad7836135de565b16600052600c6020526040600020611af082825461375a565b90555b6040519081527f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000860203392a26135de565b6111d760405160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260208152611b626040826132c0565b60405192611b6f84613288565b835260208301908152604051938493602085525160406020860152606085019061333b565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261333b565b611bd181600a5461375a565b600a55611af3565b7f728fe07b000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6020813d602011611c69575b81611c20602093836132c0565b81010312611c6557519073ffffffffffffffffffffffffffffffffffffffff82168203611c62575073ffffffffffffffffffffffffffffffffffffffff611a05565b80fd5b5080fd5b3d9150611c13565b6040513d6000823e3d90fd5b7fa9902c7e0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff16806000526003602052604060002054611977577fd0d259760000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f53ad11d80000000000000000000000000000000000000000000000000000000060005260046000fd5b611d4c915060203d602011611d52575b611d4481836132c0565b810190613a81565b83611940565b503d611d3a565b611d7773ffffffffffffffffffffffffffffffffffffffff9161362f565b7f961c9a4f000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b346102bf5760606003193601126102bf5760043567ffffffffffffffff81116102bf57611dd6903690600401613439565b9060243567ffffffffffffffff81116102bf57611df79036906004016134bc565b9060443567ffffffffffffffff81116102bf57611e189036906004016134bc565b73ffffffffffffffffffffffffffffffffffffffff6009541633141580611ed9575b61045257838614801590611ecf575b611ea55760005b868110611e5957005b80611e9f611e6d610c026001948b8b61371b565b611e78838989613777565b611e99611e91611e8986898b613777565b92369061350a565b91369061350a565b91613f86565b01611e50565b7f568efce20000000000000000000000000000000000000000000000000000000060005260046000fd5b5080861415611e49565b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611e3a565b346102bf5760006003193601126102bf57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346102bf5760206003193601126102bf576020611f6a67ffffffffffffffff611f566133bd565b166000526006602052604060002054151590565b6040519015158152f35b346102bf5760206003193601126102bf577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611fc561339a565b611fcd613cfb565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a1005b346102bf5760006003193601126102bf5760005473ffffffffffffffffffffffffffffffffffffffff811633036120a2577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346102bf5760406003193601126102bf5760043567ffffffffffffffff81116102bf576120fd903690600401613439565b6024359167ffffffffffffffff83116102bf57366023840112156102bf5782600401359167ffffffffffffffff83116102bf576024840193602436918560061b0101116102bf5761214c613cfb565b60005b81811061236e5750505060005b81811061216557005b67ffffffffffffffff61217c610c02838587613767565b16158015612339575b6122f4578061227c6121a5602061219f6001958789613767565b0161362f565b8573ffffffffffffffffffffffffffffffffffffffff80866040516121c98161326c565b6000815282602082019616865267ffffffffffffffff6121f4610c028a8d6040860199878b52613767565b16600052600c60205260406000209051815501935116167fffffffffffffffffffffffff00000000000000000000000000000000000000008354161782555115157fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b7f180c6940bd64ba8f75679203ca32f8be2f629477a3307b190656e4b14dd5ddeb6122ab610c02838688613767565b6122bb602061219f85888a613767565b6040805167ffffffffffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff91909116602083015290a10161215c565b610c029061230b9267ffffffffffffffff94613767565b7fd9a9cd68000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b5067ffffffffffffffff612351610c02838587613767565b16600052600c60205260ff60016040600020015460a01c16612185565b67ffffffffffffffff612385610c0283858761371b565b16600052600c60205260ff60016040600020015460a01c1615612457578067ffffffffffffffff6123bc610c02600194868861371b565b16600052600c6020527f7b5efb3f8090c5cfd24e170b667d0e2b6fdc3db6540d75b86d5b6655ba00eb936040600020546123f881600a5461375a565b600a5567ffffffffffffffff612412610c0285888a61371b565b16600052600c602052600084604082208281550155612435610c0284878961371b565b6040805167ffffffffffffffff9290921682526020820192909252a10161214f565b610c029061246e9267ffffffffffffffff9461371b565b7f46f5f12b000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b346102bf5760006003193601126102bf57602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b346102bf5760206003193601126102bf577f66b1c1bdec8b60a3442bb25b5b6cd6fff3d0eceb6f5390be8e2f82a8ad39b23473ffffffffffffffffffffffffffffffffffffffff61251f61339a565b612527613cfb565b6113c4600b54918381167fffffffffffffffffffffffff0000000000000000000000000000000000000000841617600b55604051938493168390929173ffffffffffffffffffffffffffffffffffffffff60209181604085019616845216910152565b346102bf5760406003193601126102bf576125a36133bd565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036102bf5767ffffffffffffffff906125d6613cfb565b169081600052600c602052600160406000200190815460ff8160a01c16156126785782547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9283169081179093556040805191909216815260208101929092527f01efd4cd7dd64263689551000d4359d6559c839f39b773b1df3fd19ff060cf5f9190819081016110de565b837f46f5f12b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102bf576126b4366133d4565b6126bf929192613cfb565b67ffffffffffffffff82166126e1816000526006602052604060002054151590565b156126fc5750610be4926126f69136916135a7565b90613d46565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102bf5761275161275961273d3661346a565b949161274a939193613cfb565b36916136b3565b9236916136b3565b7f0000000000000000000000000000000000000000000000000000000000000000156128795760005b82518110156127f5578073ffffffffffffffffffffffffffffffffffffffff6127ad60019386613787565b51166127b88161466c565b6127c4575b5001612782565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1846127bd565b5060005b8151811015610be4578073ffffffffffffffffffffffffffffffffffffffff61282460019385613787565b511680156128735761283581614a61565b612842575b505b016127f9565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a18361283a565b5061283c565b7f35f4a7b30000000000000000000000000000000000000000000000000000000060005260046000fd5b346102bf576020611f6a6128b6366133d4565b91613650565b346102bf5760006003193601126102bf57602073ffffffffffffffffffffffffffffffffffffffff600b5416604051908152f35b346102bf5760206003193601126102bf5760043567ffffffffffffffff81116102bf578060040161010060031983360301126102bf57600060405161293481613221565b52608482016129428161362f565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611d595750602482019177ffffffffffffffff000000000000000000000000000000006129a9846135de565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611c7157600091612d08575b50611d0057612a35836135de565b67ffffffffffffffff8116612a57816000526006602052604060002054151590565b15611c7d5750600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff93909316918301919091523360248301526020908290604490829073ffffffffffffffffffffffffffffffffffffffff165afa908115611c7157600091612ce9575b5015611bd957612ae1836135de565b612af360a48301916128b68386613556565b15612ca2575067ffffffffffffffff612b98612b92612b11866135de565b83606486013591166000526007602052612b8c612b87612b80600260406000200198612b767f00000000000000000000000000000000000000000000000000000000000000009a8673ffffffffffffffffffffffffffffffffffffffff8d1691614b70565b60c4890190613556565b36916135a7565b613a99565b90613b8c565b946135de565b16600052600c602052604060002060ff600182015460a01c1680600014612c9a5781545b808611612c685760208673ffffffffffffffffffffffffffffffffffffffff612c1188612c0c8460448b8b8b15612c5357612bf88482546135f3565b90555b0192612c068461362f565b90613c99565b61362f565b166040518281527f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52843392a380604051612c4a81613221565b52604051908152f35b50612c6083600a546135f3565b600a55612bfb565b85907fa17e11d50000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b600a54612bbc565b612cac9083613556565b6115b56040519283927f24eb47e50000000000000000000000000000000000000000000000000000000084526020600485015260248401916138b0565b612d02915060203d602011611d5257611d4481836132c0565b84612ad2565b612d21915060203d602011611d5257611d4481836132c0565b84612a27565b346102bf5760206003193601126102bf5767ffffffffffffffff612d496133bd565b16600052600c602052602060ff60016040600020015460a01c166040519015158152f35b346102bf5760406003193601126102bf57612d866133bd565b60243567ffffffffffffffff82168015612e7a5781156104805773ffffffffffffffffffffffffffffffffffffffff612dbe846139a2565b163303610452577f569a440e6842b5e5a7ac02286311855f5a0b81b9390909e552e82aaf02c9e9bf916110de91600052600c602052604060002060ff600182015460a01c16600014612e6557612e1582825461375a565b90555b6110b96040517f23b872dd000000000000000000000000000000000000000000000000000000006020820152336024820152306044820152826064820152606481526103e26084826132c0565b50612e7281600a5461375a565b600a55612e18565b7fd9a9cd6800000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b346102bf5760006003193601126102bf57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102bf5760206003193601126102bf576020612f0261339a565b73ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b346102bf5760006003193601126102bf57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102bf5760006003193601126102bf576111d7604051612fba6060826132c0565b602481527f53696c6f65644c6f636b52656c65617365546f6b656e506f6f6c20312e362e3060208201527f2d64657600000000000000000000000000000000000000000000000000000000604082015260405191829160208352602083019061333b565b346102bf5760206003193601126102bf5760043580156104805773ffffffffffffffffffffffffffffffffffffffff61305760006139a2565b1633036104525760008052600c6020527f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e9547f13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e89060a01c60ff16801561314a5781545b8084116110f8575015613135576130d28282546135f3565b90555b61310081337f0000000000000000000000000000000000000000000000000000000000000000613c99565b604051906000825260208201527f58fca2457646a9f47422ab9eb9bff90cef88cd8b8725ab52b1d17baa392d784e60403392a2005b5061314281600a546135f3565b600a556130d5565b600a546130ba565b346102bf5760206003193601126102bf57600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036102bf57817faff2afbf00000000000000000000000000000000000000000000000000000000602093149081156131f7575b81156131cd575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014836131c6565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506131bf565b6020810190811067ffffffffffffffff82111761323d57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761323d57604052565b6040810190811067ffffffffffffffff82111761323d57604052565b60a0810190811067ffffffffffffffff82111761323d57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761323d57604052565b67ffffffffffffffff811161323d57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106133855750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201613346565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036102bf57565b6004359067ffffffffffffffff821682036102bf57565b60406003198201126102bf5760043567ffffffffffffffff811681036102bf579160243567ffffffffffffffff81116102bf57826023820112156102bf5780600401359267ffffffffffffffff84116102bf57602484830101116102bf576024019190565b9181601f840112156102bf5782359167ffffffffffffffff83116102bf576020808501948460051b0101116102bf57565b60406003198201126102bf5760043567ffffffffffffffff81116102bf578161349591600401613439565b929092916024359067ffffffffffffffff82116102bf576134b891600401613439565b9091565b9181601f840112156102bf5782359167ffffffffffffffff83116102bf57602080850194606085020101116102bf57565b35906fffffffffffffffffffffffffffffffff821682036102bf57565b91908260609103126102bf576040516135228161326c565b809280359081151582036102bf5760406135519181938552613546602082016134ed565b6020860152016134ed565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102bf570180359067ffffffffffffffff82116102bf576020019181360383136102bf57565b9291926135b382613301565b916135c160405193846132c0565b8294818452818301116102bf578281602093846000960137010152565b3567ffffffffffffffff811681036102bf5790565b9190820391821161360057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b3573ffffffffffffffffffffffffffffffffffffffff811681036102bf5790565b613698929167ffffffffffffffff61367b9216600052600760205260056040600020019236916135a7565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff811161323d5760051b60200190565b92916136be8261369b565b936136cc60405195866132c0565b602085848152019260051b81019182116102bf57915b8183106136ee57505050565b823573ffffffffffffffffffffffffffffffffffffffff811681036102bf578152602092830192016136e2565b919081101561372b5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9190820180921161360057565b919081101561372b5760061b0190565b919081101561372b576060020190565b805182101561372b5760209160051b010190565b90600182811c921680156137e4575b60208310146137b557565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916137aa565b90604051918260008254926138028461379b565b80845293600181169081156138705750600114613829575b50613827925003836132c0565b565b90506000929192526020600020906000915b818310613854575050906020613827928201013861381a565b602091935080600191548385890101520191019091849261383b565b602093506138279592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013861381a565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b604051906138fc826132a4565b60006080838281528260208201528260408201528260608201520152565b90604051613927816132a4565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff16600052600760205261369860046040600020016137ee565b67ffffffffffffffff16600052600c60205260016040600020015460ff8160a01c166139e5575073ffffffffffffffffffffffffffffffffffffffff600b541690565b73ffffffffffffffffffffffffffffffffffffffff1690565b818110613a09575050565b600081556001016139fe565b8181029291811591840414171561360057565b9080601f830112156102bf57816020613698933591016135a7565b67ffffffffffffffff1680600052600c60205260ff60016040600020015460a01c16613a705750600a5490565b600052600c60205260406000205490565b908160209103126102bf575180151581036102bf5790565b80518015613b0857602003613aca576020818051810103126102bf5760208101519060ff8211613aca575060ff1690565b6115b5906040519182917f953576f700000000000000000000000000000000000000000000000000000000835260206004840152602483019061333b565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161360057565b60ff16604d811161360057600a0a90565b8115613b5d570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff811692828414613c9257828411613c685790613bd191613b2e565b91604d60ff8416118015613c2f575b613bf957505090613bf361369892613b42565b90613a15565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b50613c3983613b42565b8015613b5d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411613be0565b613c7191613b2e565b91604d60ff841611613bf957505090613c8c61369892613b42565b90613b53565b5050505090565b6138279273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb000000000000000000000000000000000000000000000000000000006020860152166024840152604483015260448252613cf66064836132c0565b614296565b73ffffffffffffffffffffffffffffffffffffffff600154163303613d1c57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156113c95767ffffffffffffffff81516020830120921691826000526007602052613d7b816005604060002001614b1b565b15613f425760005260086020526040600020815167ffffffffffffffff811161323d57613da8825461379b565b601f8111613f10575b506020601f8211600114613e4a5791613e24827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9593613e3a95600091613e3f575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b905560405191829160208352602083019061333b565b0390a2565b905084015138613df3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b818110613ef8575092613e3a9492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea989610613ec1575b5050811b019055611417565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880613eb5565b9192602060018192868a015181550194019201613e7a565b613f3c90836000526020600020601f840160051c81019160208510610b0b57601f0160051c01906139fe565b38613db1565b50906115b56040519283927f393b8ad2000000000000000000000000000000000000000000000000000000008452600484015260406024840152604483019061333b565b67ffffffffffffffff166000818152600660205260409020549092919015614088579161408560e09261405185613fdd7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761413b565b846000526007602052613ff48160406000206143d6565b613ffd8361413b565b8460005260076020526140178360026040600020016143d6565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6140be6138ef565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161411b602085019361411561410863ffffffff875116426135f3565b8560808901511690613a15565b9061375a565b8082101561413457505b16825263ffffffff4216905290565b9050614125565b8051156141ef576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff6020830151168110908115916141e6575b506141835750565b6064906141e4604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b9050153861417b565b6fffffffffffffffffffffffffffffffff60408201511615801590614277575b6142165750565b6064906141e4604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff602082015116151561420f565b73ffffffffffffffffffffffffffffffffffffffff6143259116916040926000808551936142c487866132c0565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af13d156143ce573d9161430983613301565b92614316875194856132c0565b83523d6000602085013e614e58565b8051908161433257505050565b602080614343938301019101613a81565b1561434b5750565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b606091614e58565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199161450f606092805461441363ffffffff8260801c16426135f3565b908161454e575b50506fffffffffffffffffffffffffffffffff600181602086015116928281541680851060001461454657508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556144c38651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b61408560405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161444a565b6fffffffffffffffffffffffffffffffff9161458383928361457c6001880154948286169560801c90613a15565b911661375a565b8082101561460257505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff0000000000000000000000000000000016178155388061441a565b905061458d565b906040519182815491828252602082019060005260206000209260005b81811061463b575050613827925003836132c0565b8454835260019485019487945060209093019201614626565b805482101561372b5760005260206000200190600090565b60008181526003602052604090205480156147fb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161360057600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116136005781810361478c575b505050600254801561475d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161471a816002614654565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6147e361479d6147ae936002614654565b90549060031b1c9283926002614654565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260036020526040600020553880806146e1565b5050600090565b60008181526006602052604090205480156147fb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161360057600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211613600578181036148f3575b505050600554801561475d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016148b0816005614654565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b6149156149046147ae936005614654565b90549060031b1c9283926005614654565b90556000526006602052604060002055388080614877565b9060018201918160005282602052604060002054801515600014614a58577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613600578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161360057818103614a21575b5050508054801561475d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906149e28282614654565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b614a41614a316147ae9386614654565b90549060031b1c92839286614654565b9055600052836020526040600020553880806149aa565b50505050600090565b80600052600360205260406000205415600014614abb576002546801000000000000000081101561323d57614aa26147ae8260018594016002556002614654565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014614abb576005546801000000000000000081101561323d57614b026147ae8260018594016005556005614654565b9055600554906000526006602052604060002055600190565b60008281526001820160205260409020546147fb578054906801000000000000000082101561323d5782614b596147ae846001809601855584614654565b905580549260005201602052604060002055600190565b929192805460ff8160a01c16158015614e50575b614e49576fffffffffffffffffffffffffffffffff81169060018301908154614bc963ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426135f3565b9081614dab575b5050848110614d295750838210614c5857507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff80614c2685602096956135f3565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b819450614c6a92505460801c926135f3565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019080821161360057614cb8614cbd9273ffffffffffffffffffffffffffffffffffffffff9461375a565b613b53565b9216918215614cf9577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff8816918215614d7b577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b828592939511614e1f57614dc6926141159160801c90613a15565b80831015614e1a5750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff0000000000000000000000000000000016178455913880614bd0565b614dd1565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b508215614b84565b91929015614ed35750815115614e6c575090565b3b15614e755790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b825190915015614ee65750805190602001fd5b6115b5906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061333b56fea164736f6c634300081a000a",
+}
+
+var SiloedLockReleaseTokenPoolABI = SiloedLockReleaseTokenPoolMetaData.ABI
+
+var SiloedLockReleaseTokenPoolBin = SiloedLockReleaseTokenPoolMetaData.Bin
+
+func DeploySiloedLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *SiloedLockReleaseTokenPool, error) {
+ parsed, err := SiloedLockReleaseTokenPoolMetaData.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(SiloedLockReleaseTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &SiloedLockReleaseTokenPool{address: address, abi: *parsed, SiloedLockReleaseTokenPoolCaller: SiloedLockReleaseTokenPoolCaller{contract: contract}, SiloedLockReleaseTokenPoolTransactor: SiloedLockReleaseTokenPoolTransactor{contract: contract}, SiloedLockReleaseTokenPoolFilterer: SiloedLockReleaseTokenPoolFilterer{contract: contract}}, nil
+}
+
+type SiloedLockReleaseTokenPool struct {
+ address common.Address
+ abi abi.ABI
+ SiloedLockReleaseTokenPoolCaller
+ SiloedLockReleaseTokenPoolTransactor
+ SiloedLockReleaseTokenPoolFilterer
+}
+
+type SiloedLockReleaseTokenPoolCaller struct {
+ contract *bind.BoundContract
+}
+
+type SiloedLockReleaseTokenPoolTransactor struct {
+ contract *bind.BoundContract
+}
+
+type SiloedLockReleaseTokenPoolFilterer struct {
+ contract *bind.BoundContract
+}
+
+type SiloedLockReleaseTokenPoolSession struct {
+ Contract *SiloedLockReleaseTokenPool
+ CallOpts bind.CallOpts
+ TransactOpts bind.TransactOpts
+}
+
+type SiloedLockReleaseTokenPoolCallerSession struct {
+ Contract *SiloedLockReleaseTokenPoolCaller
+ CallOpts bind.CallOpts
+}
+
+type SiloedLockReleaseTokenPoolTransactorSession struct {
+ Contract *SiloedLockReleaseTokenPoolTransactor
+ TransactOpts bind.TransactOpts
+}
+
+type SiloedLockReleaseTokenPoolRaw struct {
+ Contract *SiloedLockReleaseTokenPool
+}
+
+type SiloedLockReleaseTokenPoolCallerRaw struct {
+ Contract *SiloedLockReleaseTokenPoolCaller
+}
+
+type SiloedLockReleaseTokenPoolTransactorRaw struct {
+ Contract *SiloedLockReleaseTokenPoolTransactor
+}
+
+func NewSiloedLockReleaseTokenPool(address common.Address, backend bind.ContractBackend) (*SiloedLockReleaseTokenPool, error) {
+ abi, err := abi.JSON(strings.NewReader(SiloedLockReleaseTokenPoolABI))
+ if err != nil {
+ return nil, err
+ }
+ contract, err := bindSiloedLockReleaseTokenPool(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPool{address: address, abi: abi, SiloedLockReleaseTokenPoolCaller: SiloedLockReleaseTokenPoolCaller{contract: contract}, SiloedLockReleaseTokenPoolTransactor: SiloedLockReleaseTokenPoolTransactor{contract: contract}, SiloedLockReleaseTokenPoolFilterer: SiloedLockReleaseTokenPoolFilterer{contract: contract}}, nil
+}
+
+func NewSiloedLockReleaseTokenPoolCaller(address common.Address, caller bind.ContractCaller) (*SiloedLockReleaseTokenPoolCaller, error) {
+ contract, err := bindSiloedLockReleaseTokenPool(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolCaller{contract: contract}, nil
+}
+
+func NewSiloedLockReleaseTokenPoolTransactor(address common.Address, transactor bind.ContractTransactor) (*SiloedLockReleaseTokenPoolTransactor, error) {
+ contract, err := bindSiloedLockReleaseTokenPool(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolTransactor{contract: contract}, nil
+}
+
+func NewSiloedLockReleaseTokenPoolFilterer(address common.Address, filterer bind.ContractFilterer) (*SiloedLockReleaseTokenPoolFilterer, error) {
+ contract, err := bindSiloedLockReleaseTokenPool(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolFilterer{contract: contract}, nil
+}
+
+func bindSiloedLockReleaseTokenPool(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := SiloedLockReleaseTokenPoolMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SiloedLockReleaseTokenPool.Contract.SiloedLockReleaseTokenPoolCaller.contract.Call(opts, result, method, params...)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SiloedLockReleaseTokenPoolTransactor.contract.Transfer(opts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SiloedLockReleaseTokenPoolTransactor.contract.Transact(opts, method, params...)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SiloedLockReleaseTokenPool.Contract.contract.Call(opts, result, method, params...)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.contract.Transfer(opts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.contract.Transact(opts, method, params...)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetAllowList(opts *bind.CallOpts) ([]common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetAllowList() ([]common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAllowList(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetAllowList() ([]common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAllowList(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetAllowListEnabled(opts *bind.CallOpts) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getAllowListEnabled")
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetAllowListEnabled() (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAllowListEnabled(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetAllowListEnabled() (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAllowListEnabled(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetAvailableTokens(opts *bind.CallOpts, remoteChainSelector uint64) (*big.Int, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getAvailableTokens", remoteChainSelector)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetAvailableTokens(remoteChainSelector uint64) (*big.Int, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAvailableTokens(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetAvailableTokens(remoteChainSelector uint64) (*big.Int, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetAvailableTokens(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetCurrentInboundRateLimiterState(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetCurrentInboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetCurrentInboundRateLimiterState(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetCurrentOutboundRateLimiterState(remoteChainSelector uint64) (RateLimiterTokenBucket, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetCurrentOutboundRateLimiterState(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRateLimitAdmin() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRateLimitAdmin(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRateLimitAdmin() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRateLimitAdmin(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRebalancer(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getRebalancer")
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRebalancer() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRebalancer(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRebalancer() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRebalancer(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector)
+
+ if err != nil {
+ return *new([][]byte), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRemotePools(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRemotePools(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRemoteToken(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRemoteToken(remoteChainSelector uint64) ([]byte, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRemoteToken(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRmnProxy(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRmnProxy() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRmnProxy(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRmnProxy() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRmnProxy(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetRouter(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetRouter() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRouter(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetRouter() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetRouter(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetSiloRebalancer(opts *bind.CallOpts, remoteChainSelector uint64) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getSiloRebalancer", remoteChainSelector)
+
+ if err != nil {
+ return *new(common.Address), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetSiloRebalancer(remoteChainSelector uint64) (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetSiloRebalancer(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetSiloRebalancer(remoteChainSelector uint64) (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetSiloRebalancer(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetSupportedChains(opts *bind.CallOpts) ([]uint64, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getSupportedChains")
+
+ if err != nil {
+ return *new([]uint64), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new([]uint64)).(*[]uint64)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetSupportedChains() ([]uint64, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetSupportedChains(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetSupportedChains() ([]uint64, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetSupportedChains(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetToken(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetToken() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetToken(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetToken() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetToken(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getTokenDecimals")
+
+ if err != nil {
+ return *new(uint8), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetTokenDecimals() (uint8, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetTokenDecimals(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetTokenDecimals() (uint8, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetTokenDecimals(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) GetUnsiloedLiquidity(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "getUnsiloedLiquidity")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) GetUnsiloedLiquidity() (*big.Int, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetUnsiloedLiquidity(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) GetUnsiloedLiquidity() (*big.Int, error) {
+ return _SiloedLockReleaseTokenPool.Contract.GetUnsiloedLiquidity(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress)
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsRemotePool(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsRemotePool(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) IsSiloed(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "isSiloed", remoteChainSelector)
+
+ if err != nil {
+ return *new(bool), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) IsSiloed(remoteChainSelector uint64) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSiloed(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) IsSiloed(remoteChainSelector uint64) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSiloed(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSupportedChain(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) IsSupportedChain(remoteChainSelector uint64) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSupportedChain(&_SiloedLockReleaseTokenPool.CallOpts, remoteChainSelector)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) IsSupportedToken(token common.Address) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSupportedToken(&_SiloedLockReleaseTokenPool.CallOpts, token)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) IsSupportedToken(token common.Address) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.IsSupportedToken(&_SiloedLockReleaseTokenPool.CallOpts, token)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) Owner(opts *bind.CallOpts) (common.Address, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) Owner() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.Owner(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) Owner() (common.Address, error) {
+ return _SiloedLockReleaseTokenPool.Contract.Owner(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SupportsInterface(interfaceId [4]byte) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SupportsInterface(&_SiloedLockReleaseTokenPool.CallOpts, interfaceId)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SupportsInterface(&_SiloedLockReleaseTokenPool.CallOpts, interfaceId)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _SiloedLockReleaseTokenPool.contract.Call(opts, &out, "typeAndVersion")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) TypeAndVersion() (string, error) {
+ return _SiloedLockReleaseTokenPool.Contract.TypeAndVersion(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolCallerSession) TypeAndVersion() (string, error) {
+ return _SiloedLockReleaseTokenPool.Contract.TypeAndVersion(&_SiloedLockReleaseTokenPool.CallOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "acceptOwnership")
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) AcceptOwnership() (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.AcceptOwnership(&_SiloedLockReleaseTokenPool.TransactOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) AcceptOwnership() (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.AcceptOwnership(&_SiloedLockReleaseTokenPool.TransactOpts)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.AddRemotePool(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.AddRemotePool(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ApplyAllowListUpdates(&_SiloedLockReleaseTokenPool.TransactOpts, removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) ApplyAllowListUpdates(removes []common.Address, adds []common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ApplyAllowListUpdates(&_SiloedLockReleaseTokenPool.TransactOpts, removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ApplyChainUpdates(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ApplyChainUpdates(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "lockOrBurn", lockOrBurnIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.LockOrBurn(&_SiloedLockReleaseTokenPool.TransactOpts, lockOrBurnIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) LockOrBurn(lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.LockOrBurn(&_SiloedLockReleaseTokenPool.TransactOpts, lockOrBurnIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) ProvideLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "provideLiquidity", amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) ProvideLiquidity(amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ProvideLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) ProvideLiquidity(amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ProvideLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) ProvideSiloedLiquidity(opts *bind.TransactOpts, remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "provideSiloedLiquidity", remoteChainSelector, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) ProvideSiloedLiquidity(remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ProvideSiloedLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) ProvideSiloedLiquidity(remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ProvideSiloedLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "releaseOrMint", releaseOrMintIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ReleaseOrMint(&_SiloedLockReleaseTokenPool.TransactOpts, releaseOrMintIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.ReleaseOrMint(&_SiloedLockReleaseTokenPool.TransactOpts, releaseOrMintIn)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.RemoveRemotePool(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.RemoveRemotePool(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetChainRateLimiterConfig(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetChainRateLimiterConfig(remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetChainRateLimiterConfig(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRateLimitAdmin(&_SiloedLockReleaseTokenPool.TransactOpts, rateLimitAdmin)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRateLimitAdmin(&_SiloedLockReleaseTokenPool.TransactOpts, rateLimitAdmin)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetRebalancer(opts *bind.TransactOpts, newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setRebalancer", newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetRebalancer(newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRebalancer(&_SiloedLockReleaseTokenPool.TransactOpts, newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetRebalancer(newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRebalancer(&_SiloedLockReleaseTokenPool.TransactOpts, newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setRouter", newRouter)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetRouter(newRouter common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRouter(&_SiloedLockReleaseTokenPool.TransactOpts, newRouter)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetRouter(newRouter common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetRouter(&_SiloedLockReleaseTokenPool.TransactOpts, newRouter)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) SetSiloRebalancer(opts *bind.TransactOpts, remoteChainSelector uint64, newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "setSiloRebalancer", remoteChainSelector, newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) SetSiloRebalancer(remoteChainSelector uint64, newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetSiloRebalancer(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) SetSiloRebalancer(remoteChainSelector uint64, newRebalancer common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.SetSiloRebalancer(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, newRebalancer)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "transferOwnership", to)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) TransferOwnership(to common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.TransferOwnership(&_SiloedLockReleaseTokenPool.TransactOpts, to)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.TransferOwnership(&_SiloedLockReleaseTokenPool.TransactOpts, to)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) UpdateSiloDesignations(opts *bind.TransactOpts, removes []uint64, adds []SiloedLockReleaseTokenPoolSiloConfigUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "updateSiloDesignations", removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) UpdateSiloDesignations(removes []uint64, adds []SiloedLockReleaseTokenPoolSiloConfigUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.UpdateSiloDesignations(&_SiloedLockReleaseTokenPool.TransactOpts, removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) UpdateSiloDesignations(removes []uint64, adds []SiloedLockReleaseTokenPoolSiloConfigUpdate) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.UpdateSiloDesignations(&_SiloedLockReleaseTokenPool.TransactOpts, removes, adds)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) WithdrawLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "withdrawLiquidity", amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) WithdrawLiquidity(amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.WithdrawLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) WithdrawLiquidity(amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.WithdrawLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactor) WithdrawSiloedLiquidity(opts *bind.TransactOpts, remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.contract.Transact(opts, "withdrawSiloedLiquidity", remoteChainSelector, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolSession) WithdrawSiloedLiquidity(remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.WithdrawSiloedLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, amount)
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolTransactorSession) WithdrawSiloedLiquidity(remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error) {
+ return _SiloedLockReleaseTokenPool.Contract.WithdrawSiloedLiquidity(&_SiloedLockReleaseTokenPool.TransactOpts, remoteChainSelector, amount)
+}
+
+type SiloedLockReleaseTokenPoolAllowListAddIterator struct {
+ Event *SiloedLockReleaseTokenPoolAllowListAdd
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListAddIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolAllowListAdd)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolAllowListAdd)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListAddIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListAddIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolAllowListAdd struct {
+ Sender common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterAllowListAdd(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolAllowListAddIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "AllowListAdd")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolAllowListAddIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "AllowListAdd", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolAllowListAdd) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolAllowListAdd)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseAllowListAdd(log types.Log) (*SiloedLockReleaseTokenPoolAllowListAdd, error) {
+ event := new(SiloedLockReleaseTokenPoolAllowListAdd)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "AllowListAdd", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolAllowListRemoveIterator struct {
+ Event *SiloedLockReleaseTokenPoolAllowListRemove
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListRemoveIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolAllowListRemove)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolAllowListRemove)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListRemoveIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolAllowListRemoveIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolAllowListRemove struct {
+ Sender common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterAllowListRemove(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolAllowListRemoveIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "AllowListRemove")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolAllowListRemoveIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "AllowListRemove", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolAllowListRemove) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolAllowListRemove)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseAllowListRemove(log types.Log) (*SiloedLockReleaseTokenPoolAllowListRemove, error) {
+ event := new(SiloedLockReleaseTokenPoolAllowListRemove)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "AllowListRemove", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolBurnedIterator struct {
+ Event *SiloedLockReleaseTokenPoolBurned
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolBurnedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolBurned)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolBurned)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolBurnedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolBurnedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolBurned struct {
+ Sender common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*SiloedLockReleaseTokenPoolBurnedIterator, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "Burned", senderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolBurnedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "Burned", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchBurned(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolBurned, sender []common.Address) (event.Subscription, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolBurned)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseBurned(log types.Log) (*SiloedLockReleaseTokenPoolBurned, error) {
+ event := new(SiloedLockReleaseTokenPoolBurned)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "Burned", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolChainAddedIterator struct {
+ Event *SiloedLockReleaseTokenPoolChainAdded
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolChainAddedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolChainAddedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolChainAddedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolChainAdded struct {
+ RemoteChainSelector uint64
+ RemoteToken []byte
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterChainAdded(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainAddedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ChainAdded")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolChainAddedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ChainAdded", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchChainAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainAdded) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolChainAdded)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseChainAdded(log types.Log) (*SiloedLockReleaseTokenPoolChainAdded, error) {
+ event := new(SiloedLockReleaseTokenPoolChainAdded)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainAdded", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolChainConfiguredIterator struct {
+ Event *SiloedLockReleaseTokenPoolChainConfigured
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolChainConfiguredIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainConfigured)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainConfigured)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolChainConfiguredIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolChainConfiguredIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolChainConfigured struct {
+ RemoteChainSelector uint64
+ OutboundRateLimiterConfig RateLimiterConfig
+ InboundRateLimiterConfig RateLimiterConfig
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterChainConfigured(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainConfiguredIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ChainConfigured")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolChainConfiguredIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ChainConfigured", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainConfigured) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolChainConfigured)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseChainConfigured(log types.Log) (*SiloedLockReleaseTokenPoolChainConfigured, error) {
+ event := new(SiloedLockReleaseTokenPoolChainConfigured)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainConfigured", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolChainRemovedIterator struct {
+ Event *SiloedLockReleaseTokenPoolChainRemoved
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolChainRemovedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolChainRemovedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolChainRemovedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolChainRemoved struct {
+ RemoteChainSelector uint64
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterChainRemoved(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainRemovedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ChainRemoved")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolChainRemovedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ChainRemoved", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainRemoved) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolChainRemoved)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseChainRemoved(log types.Log) (*SiloedLockReleaseTokenPoolChainRemoved, error) {
+ event := new(SiloedLockReleaseTokenPoolChainRemoved)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainRemoved", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolChainSiloedIterator struct {
+ Event *SiloedLockReleaseTokenPoolChainSiloed
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolChainSiloedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainSiloed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainSiloed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolChainSiloedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolChainSiloedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolChainSiloed struct {
+ RemoteChainSelector uint64
+ Rebalancer common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterChainSiloed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainSiloedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ChainSiloed")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolChainSiloedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ChainSiloed", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchChainSiloed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainSiloed) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "ChainSiloed")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolChainSiloed)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainSiloed", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseChainSiloed(log types.Log) (*SiloedLockReleaseTokenPoolChainSiloed, error) {
+ event := new(SiloedLockReleaseTokenPoolChainSiloed)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainSiloed", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolChainUnsiloedIterator struct {
+ Event *SiloedLockReleaseTokenPoolChainUnsiloed
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolChainUnsiloedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainUnsiloed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolChainUnsiloed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolChainUnsiloedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolChainUnsiloedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolChainUnsiloed struct {
+ RemoteChainSelector uint64
+ AmountUnsiloed *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterChainUnsiloed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainUnsiloedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ChainUnsiloed")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolChainUnsiloedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ChainUnsiloed", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchChainUnsiloed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainUnsiloed) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "ChainUnsiloed")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolChainUnsiloed)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainUnsiloed", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseChainUnsiloed(log types.Log) (*SiloedLockReleaseTokenPoolChainUnsiloed, error) {
+ event := new(SiloedLockReleaseTokenPoolChainUnsiloed)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ChainUnsiloed", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolConfigChangedIterator struct {
+ Event *SiloedLockReleaseTokenPoolConfigChanged
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolConfigChangedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolConfigChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolConfigChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolConfigChangedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolConfigChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolConfigChanged struct {
+ Config RateLimiterConfig
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolConfigChangedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "ConfigChanged")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolConfigChangedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolConfigChanged) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolConfigChanged)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseConfigChanged(log types.Log) (*SiloedLockReleaseTokenPoolConfigChanged, error) {
+ event := new(SiloedLockReleaseTokenPoolConfigChanged)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "ConfigChanged", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolLiquidityAddedIterator struct {
+ Event *SiloedLockReleaseTokenPoolLiquidityAdded
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityAddedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLiquidityAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLiquidityAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityAddedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityAddedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolLiquidityAdded struct {
+ RemoteChainSelector uint64
+ Provider common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterLiquidityAdded(opts *bind.FilterOpts, provider []common.Address) (*SiloedLockReleaseTokenPoolLiquidityAddedIterator, error) {
+
+ var providerRule []interface{}
+ for _, providerItem := range provider {
+ providerRule = append(providerRule, providerItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "LiquidityAdded", providerRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolLiquidityAddedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "LiquidityAdded", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchLiquidityAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLiquidityAdded, provider []common.Address) (event.Subscription, error) {
+
+ var providerRule []interface{}
+ for _, providerItem := range provider {
+ providerRule = append(providerRule, providerItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "LiquidityAdded", providerRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolLiquidityAdded)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "LiquidityAdded", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseLiquidityAdded(log types.Log) (*SiloedLockReleaseTokenPoolLiquidityAdded, error) {
+ event := new(SiloedLockReleaseTokenPoolLiquidityAdded)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "LiquidityAdded", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolLiquidityRemovedIterator struct {
+ Event *SiloedLockReleaseTokenPoolLiquidityRemoved
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityRemovedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLiquidityRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLiquidityRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityRemovedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolLiquidityRemovedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolLiquidityRemoved struct {
+ RemoteChainSelector uint64
+ Remover common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterLiquidityRemoved(opts *bind.FilterOpts, remover []common.Address) (*SiloedLockReleaseTokenPoolLiquidityRemovedIterator, error) {
+
+ var removerRule []interface{}
+ for _, removerItem := range remover {
+ removerRule = append(removerRule, removerItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "LiquidityRemoved", removerRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolLiquidityRemovedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "LiquidityRemoved", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchLiquidityRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLiquidityRemoved, remover []common.Address) (event.Subscription, error) {
+
+ var removerRule []interface{}
+ for _, removerItem := range remover {
+ removerRule = append(removerRule, removerItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "LiquidityRemoved", removerRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolLiquidityRemoved)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "LiquidityRemoved", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseLiquidityRemoved(log types.Log) (*SiloedLockReleaseTokenPoolLiquidityRemoved, error) {
+ event := new(SiloedLockReleaseTokenPoolLiquidityRemoved)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "LiquidityRemoved", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolLockedIterator struct {
+ Event *SiloedLockReleaseTokenPoolLocked
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolLockedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLocked)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolLocked)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolLockedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolLockedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolLocked struct {
+ Sender common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*SiloedLockReleaseTokenPoolLockedIterator, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "Locked", senderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolLockedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "Locked", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchLocked(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLocked, sender []common.Address) (event.Subscription, error) {
+
+ var senderRule []interface{}
+ for _, senderItem := range sender {
+ senderRule = append(senderRule, senderItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolLocked)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseLocked(log types.Log) (*SiloedLockReleaseTokenPoolLocked, error) {
+ event := new(SiloedLockReleaseTokenPoolLocked)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "Locked", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolMintedIterator struct {
+ Event *SiloedLockReleaseTokenPoolMinted
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolMintedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolMinted)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolMinted)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolMintedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolMintedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolMinted struct {
+ Sender common.Address
+ Recipient common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*SiloedLockReleaseTokenPoolMintedIterator, 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 := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "Minted", senderRule, recipientRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolMintedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "Minted", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchMinted(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolMinted, 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 := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolMinted)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseMinted(log types.Log) (*SiloedLockReleaseTokenPoolMinted, error) {
+ event := new(SiloedLockReleaseTokenPoolMinted)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "Minted", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator struct {
+ Event *SiloedLockReleaseTokenPoolOwnershipTransferRequested
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolOwnershipTransferRequested)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolOwnershipTransferRequested)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolOwnershipTransferRequested struct {
+ From common.Address
+ To common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator, 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 := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolOwnershipTransferRequested, 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 := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolOwnershipTransferRequested)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseOwnershipTransferRequested(log types.Log) (*SiloedLockReleaseTokenPoolOwnershipTransferRequested, error) {
+ event := new(SiloedLockReleaseTokenPoolOwnershipTransferRequested)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolOwnershipTransferredIterator struct {
+ Event *SiloedLockReleaseTokenPoolOwnershipTransferred
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferredIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolOwnershipTransferred)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferredIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolOwnershipTransferredIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolOwnershipTransferred struct {
+ From common.Address
+ To common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SiloedLockReleaseTokenPoolOwnershipTransferredIterator, 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 := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolOwnershipTransferredIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolOwnershipTransferred, 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 := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolOwnershipTransferred)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseOwnershipTransferred(log types.Log) (*SiloedLockReleaseTokenPoolOwnershipTransferred, error) {
+ event := new(SiloedLockReleaseTokenPoolOwnershipTransferred)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolRateLimitAdminSetIterator struct {
+ Event *SiloedLockReleaseTokenPoolRateLimitAdminSet
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolRateLimitAdminSetIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRateLimitAdminSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRateLimitAdminSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolRateLimitAdminSetIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolRateLimitAdminSetIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolRateLimitAdminSet struct {
+ RateLimitAdmin common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolRateLimitAdminSetIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolRateLimitAdminSetIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRateLimitAdminSet) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolRateLimitAdminSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*SiloedLockReleaseTokenPoolRateLimitAdminSet, error) {
+ event := new(SiloedLockReleaseTokenPoolRateLimitAdminSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolReleasedIterator struct {
+ Event *SiloedLockReleaseTokenPoolReleased
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolReleasedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolReleased)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolReleased)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolReleasedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolReleasedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolReleased struct {
+ Sender common.Address
+ Recipient common.Address
+ Amount *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*SiloedLockReleaseTokenPoolReleasedIterator, 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 := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "Released", senderRule, recipientRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolReleasedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "Released", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchReleased(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolReleased, 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 := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolReleased)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseReleased(log types.Log) (*SiloedLockReleaseTokenPoolReleased, error) {
+ event := new(SiloedLockReleaseTokenPoolReleased)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "Released", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolRemotePoolAddedIterator struct {
+ Event *SiloedLockReleaseTokenPoolRemotePoolAdded
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolAddedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRemotePoolAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRemotePoolAdded)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolAddedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolAddedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolRemotePoolAdded struct {
+ RemoteChainSelector uint64
+ RemotePoolAddress []byte
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolRemotePoolAddedIterator, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolRemotePoolAddedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolRemotePoolAdded)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*SiloedLockReleaseTokenPoolRemotePoolAdded, error) {
+ event := new(SiloedLockReleaseTokenPoolRemotePoolAdded)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolRemotePoolRemovedIterator struct {
+ Event *SiloedLockReleaseTokenPoolRemotePoolRemoved
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolRemovedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRemotePoolRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRemotePoolRemoved)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolRemovedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolRemotePoolRemovedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolRemotePoolRemoved struct {
+ RemoteChainSelector uint64
+ RemotePoolAddress []byte
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolRemotePoolRemovedIterator, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolRemotePoolRemovedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolRemotePoolRemoved)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*SiloedLockReleaseTokenPoolRemotePoolRemoved, error) {
+ event := new(SiloedLockReleaseTokenPoolRemotePoolRemoved)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolRouterUpdatedIterator struct {
+ Event *SiloedLockReleaseTokenPoolRouterUpdated
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolRouterUpdatedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRouterUpdated)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolRouterUpdated)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolRouterUpdatedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolRouterUpdatedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolRouterUpdated struct {
+ OldRouter common.Address
+ NewRouter common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterRouterUpdated(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolRouterUpdatedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "RouterUpdated")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolRouterUpdatedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "RouterUpdated", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRouterUpdated) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolRouterUpdated)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseRouterUpdated(log types.Log) (*SiloedLockReleaseTokenPoolRouterUpdated, error) {
+ event := new(SiloedLockReleaseTokenPoolRouterUpdated)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "RouterUpdated", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolSiloRebalancerSetIterator struct {
+ Event *SiloedLockReleaseTokenPoolSiloRebalancerSet
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolSiloRebalancerSetIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolSiloRebalancerSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolSiloRebalancerSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolSiloRebalancerSetIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolSiloRebalancerSetIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolSiloRebalancerSet struct {
+ RemoteChainSelector uint64
+ OldRebalancer common.Address
+ NewRebalancer common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterSiloRebalancerSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolSiloRebalancerSetIterator, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "SiloRebalancerSet", remoteChainSelectorRule)
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolSiloRebalancerSetIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "SiloRebalancerSet", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchSiloRebalancerSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolSiloRebalancerSet, remoteChainSelector []uint64) (event.Subscription, error) {
+
+ var remoteChainSelectorRule []interface{}
+ for _, remoteChainSelectorItem := range remoteChainSelector {
+ remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem)
+ }
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "SiloRebalancerSet", 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(SiloedLockReleaseTokenPoolSiloRebalancerSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "SiloRebalancerSet", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseSiloRebalancerSet(log types.Log) (*SiloedLockReleaseTokenPoolSiloRebalancerSet, error) {
+ event := new(SiloedLockReleaseTokenPoolSiloRebalancerSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "SiloRebalancerSet", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolTokensConsumedIterator struct {
+ Event *SiloedLockReleaseTokenPoolTokensConsumed
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolTokensConsumedIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolTokensConsumed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolTokensConsumed)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolTokensConsumedIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolTokensConsumedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolTokensConsumed struct {
+ Tokens *big.Int
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolTokensConsumedIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "TokensConsumed")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolTokensConsumedIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolTokensConsumed) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.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(SiloedLockReleaseTokenPoolTokensConsumed)
+ if err := _SiloedLockReleaseTokenPool.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 (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseTokensConsumed(log types.Log) (*SiloedLockReleaseTokenPoolTokensConsumed, error) {
+ event := new(SiloedLockReleaseTokenPoolTokensConsumed)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "TokensConsumed", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+type SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator struct {
+ Event *SiloedLockReleaseTokenPoolUnsiloedRebalancerSet
+
+ contract *bind.BoundContract
+ event string
+
+ logs chan types.Log
+ sub ethereum.Subscription
+ done bool
+ fail error
+}
+
+func (it *SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator) Next() bool {
+
+ if it.fail != nil {
+ return false
+ }
+
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolUnsiloedRebalancerSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+
+ select {
+ case log := <-it.logs:
+ it.Event = new(SiloedLockReleaseTokenPoolUnsiloedRebalancerSet)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+func (it *SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator) Error() error {
+ return it.fail
+}
+
+func (it *SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+type SiloedLockReleaseTokenPoolUnsiloedRebalancerSet struct {
+ OldRebalancer common.Address
+ NewRebalancer common.Address
+ Raw types.Log
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) FilterUnsiloedRebalancerSet(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.FilterLogs(opts, "UnsiloedRebalancerSet")
+ if err != nil {
+ return nil, err
+ }
+ return &SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator{contract: _SiloedLockReleaseTokenPool.contract, event: "UnsiloedRebalancerSet", logs: logs, sub: sub}, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) WatchUnsiloedRebalancerSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolUnsiloedRebalancerSet) (event.Subscription, error) {
+
+ logs, sub, err := _SiloedLockReleaseTokenPool.contract.WatchLogs(opts, "UnsiloedRebalancerSet")
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+
+ event := new(SiloedLockReleaseTokenPoolUnsiloedRebalancerSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "UnsiloedRebalancerSet", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPoolFilterer) ParseUnsiloedRebalancerSet(log types.Log) (*SiloedLockReleaseTokenPoolUnsiloedRebalancerSet, error) {
+ event := new(SiloedLockReleaseTokenPoolUnsiloedRebalancerSet)
+ if err := _SiloedLockReleaseTokenPool.contract.UnpackLog(event, "UnsiloedRebalancerSet", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPool) ParseLog(log types.Log) (generated.AbigenLog, error) {
+ switch log.Topics[0] {
+ case _SiloedLockReleaseTokenPool.abi.Events["AllowListAdd"].ID:
+ return _SiloedLockReleaseTokenPool.ParseAllowListAdd(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["AllowListRemove"].ID:
+ return _SiloedLockReleaseTokenPool.ParseAllowListRemove(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["Burned"].ID:
+ return _SiloedLockReleaseTokenPool.ParseBurned(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ChainAdded"].ID:
+ return _SiloedLockReleaseTokenPool.ParseChainAdded(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ChainConfigured"].ID:
+ return _SiloedLockReleaseTokenPool.ParseChainConfigured(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ChainRemoved"].ID:
+ return _SiloedLockReleaseTokenPool.ParseChainRemoved(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ChainSiloed"].ID:
+ return _SiloedLockReleaseTokenPool.ParseChainSiloed(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ChainUnsiloed"].ID:
+ return _SiloedLockReleaseTokenPool.ParseChainUnsiloed(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["ConfigChanged"].ID:
+ return _SiloedLockReleaseTokenPool.ParseConfigChanged(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["LiquidityAdded"].ID:
+ return _SiloedLockReleaseTokenPool.ParseLiquidityAdded(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["LiquidityRemoved"].ID:
+ return _SiloedLockReleaseTokenPool.ParseLiquidityRemoved(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["Locked"].ID:
+ return _SiloedLockReleaseTokenPool.ParseLocked(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["Minted"].ID:
+ return _SiloedLockReleaseTokenPool.ParseMinted(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["OwnershipTransferRequested"].ID:
+ return _SiloedLockReleaseTokenPool.ParseOwnershipTransferRequested(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["OwnershipTransferred"].ID:
+ return _SiloedLockReleaseTokenPool.ParseOwnershipTransferred(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["RateLimitAdminSet"].ID:
+ return _SiloedLockReleaseTokenPool.ParseRateLimitAdminSet(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["Released"].ID:
+ return _SiloedLockReleaseTokenPool.ParseReleased(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["RemotePoolAdded"].ID:
+ return _SiloedLockReleaseTokenPool.ParseRemotePoolAdded(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["RemotePoolRemoved"].ID:
+ return _SiloedLockReleaseTokenPool.ParseRemotePoolRemoved(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["RouterUpdated"].ID:
+ return _SiloedLockReleaseTokenPool.ParseRouterUpdated(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["SiloRebalancerSet"].ID:
+ return _SiloedLockReleaseTokenPool.ParseSiloRebalancerSet(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["TokensConsumed"].ID:
+ return _SiloedLockReleaseTokenPool.ParseTokensConsumed(log)
+ case _SiloedLockReleaseTokenPool.abi.Events["UnsiloedRebalancerSet"].ID:
+ return _SiloedLockReleaseTokenPool.ParseUnsiloedRebalancerSet(log)
+
+ default:
+ return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0])
+ }
+}
+
+func (SiloedLockReleaseTokenPoolAllowListAdd) Topic() common.Hash {
+ return common.HexToHash("0x2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d8")
+}
+
+func (SiloedLockReleaseTokenPoolAllowListRemove) Topic() common.Hash {
+ return common.HexToHash("0x800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf7566")
+}
+
+func (SiloedLockReleaseTokenPoolBurned) Topic() common.Hash {
+ return common.HexToHash("0x696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7")
+}
+
+func (SiloedLockReleaseTokenPoolChainAdded) Topic() common.Hash {
+ return common.HexToHash("0x8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2")
+}
+
+func (SiloedLockReleaseTokenPoolChainConfigured) Topic() common.Hash {
+ return common.HexToHash("0x0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b")
+}
+
+func (SiloedLockReleaseTokenPoolChainRemoved) Topic() common.Hash {
+ return common.HexToHash("0x5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916")
+}
+
+func (SiloedLockReleaseTokenPoolChainSiloed) Topic() common.Hash {
+ return common.HexToHash("0x180c6940bd64ba8f75679203ca32f8be2f629477a3307b190656e4b14dd5ddeb")
+}
+
+func (SiloedLockReleaseTokenPoolChainUnsiloed) Topic() common.Hash {
+ return common.HexToHash("0x7b5efb3f8090c5cfd24e170b667d0e2b6fdc3db6540d75b86d5b6655ba00eb93")
+}
+
+func (SiloedLockReleaseTokenPoolConfigChanged) Topic() common.Hash {
+ return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19")
+}
+
+func (SiloedLockReleaseTokenPoolLiquidityAdded) Topic() common.Hash {
+ return common.HexToHash("0x569a440e6842b5e5a7ac02286311855f5a0b81b9390909e552e82aaf02c9e9bf")
+}
+
+func (SiloedLockReleaseTokenPoolLiquidityRemoved) Topic() common.Hash {
+ return common.HexToHash("0x58fca2457646a9f47422ab9eb9bff90cef88cd8b8725ab52b1d17baa392d784e")
+}
+
+func (SiloedLockReleaseTokenPoolLocked) Topic() common.Hash {
+ return common.HexToHash("0x9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd60008")
+}
+
+func (SiloedLockReleaseTokenPoolMinted) Topic() common.Hash {
+ return common.HexToHash("0x9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0")
+}
+
+func (SiloedLockReleaseTokenPoolOwnershipTransferRequested) Topic() common.Hash {
+ return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278")
+}
+
+func (SiloedLockReleaseTokenPoolOwnershipTransferred) Topic() common.Hash {
+ return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0")
+}
+
+func (SiloedLockReleaseTokenPoolRateLimitAdminSet) Topic() common.Hash {
+ return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174")
+}
+
+func (SiloedLockReleaseTokenPoolReleased) Topic() common.Hash {
+ return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52")
+}
+
+func (SiloedLockReleaseTokenPoolRemotePoolAdded) Topic() common.Hash {
+ return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea")
+}
+
+func (SiloedLockReleaseTokenPoolRemotePoolRemoved) Topic() common.Hash {
+ return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76")
+}
+
+func (SiloedLockReleaseTokenPoolRouterUpdated) Topic() common.Hash {
+ return common.HexToHash("0x02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684")
+}
+
+func (SiloedLockReleaseTokenPoolSiloRebalancerSet) Topic() common.Hash {
+ return common.HexToHash("0x01efd4cd7dd64263689551000d4359d6559c839f39b773b1df3fd19ff060cf5f")
+}
+
+func (SiloedLockReleaseTokenPoolTokensConsumed) Topic() common.Hash {
+ return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a")
+}
+
+func (SiloedLockReleaseTokenPoolUnsiloedRebalancerSet) Topic() common.Hash {
+ return common.HexToHash("0x66b1c1bdec8b60a3442bb25b5b6cd6fff3d0eceb6f5390be8e2f82a8ad39b234")
+}
+
+func (_SiloedLockReleaseTokenPool *SiloedLockReleaseTokenPool) Address() common.Address {
+ return _SiloedLockReleaseTokenPool.address
+}
+
+type SiloedLockReleaseTokenPoolInterface interface {
+ GetAllowList(opts *bind.CallOpts) ([]common.Address, error)
+
+ GetAllowListEnabled(opts *bind.CallOpts) (bool, error)
+
+ GetAvailableTokens(opts *bind.CallOpts, remoteChainSelector uint64) (*big.Int, error)
+
+ GetCurrentInboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error)
+
+ GetCurrentOutboundRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64) (RateLimiterTokenBucket, error)
+
+ GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error)
+
+ GetRebalancer(opts *bind.CallOpts) (common.Address, error)
+
+ GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error)
+
+ GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error)
+
+ GetRmnProxy(opts *bind.CallOpts) (common.Address, error)
+
+ GetRouter(opts *bind.CallOpts) (common.Address, error)
+
+ GetSiloRebalancer(opts *bind.CallOpts, remoteChainSelector uint64) (common.Address, error)
+
+ GetSupportedChains(opts *bind.CallOpts) ([]uint64, error)
+
+ GetToken(opts *bind.CallOpts) (common.Address, error)
+
+ GetTokenDecimals(opts *bind.CallOpts) (uint8, error)
+
+ GetUnsiloedLiquidity(opts *bind.CallOpts) (*big.Int, error)
+
+ IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error)
+
+ IsSiloed(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error)
+
+ IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error)
+
+ IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error)
+
+ Owner(opts *bind.CallOpts) (common.Address, error)
+
+ SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error)
+
+ TypeAndVersion(opts *bind.CallOpts) (string, error)
+
+ AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error)
+
+ AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error)
+
+ ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error)
+
+ ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error)
+
+ LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error)
+
+ ProvideLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error)
+
+ ProvideSiloedLiquidity(opts *bind.TransactOpts, remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error)
+
+ ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error)
+
+ RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error)
+
+ SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error)
+
+ SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error)
+
+ SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error)
+
+ SetRebalancer(opts *bind.TransactOpts, newRebalancer common.Address) (*types.Transaction, error)
+
+ SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error)
+
+ SetSiloRebalancer(opts *bind.TransactOpts, remoteChainSelector uint64, newRebalancer common.Address) (*types.Transaction, error)
+
+ TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error)
+
+ UpdateSiloDesignations(opts *bind.TransactOpts, removes []uint64, adds []SiloedLockReleaseTokenPoolSiloConfigUpdate) (*types.Transaction, error)
+
+ WithdrawLiquidity(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error)
+
+ WithdrawSiloedLiquidity(opts *bind.TransactOpts, remoteChainSelector uint64, amount *big.Int) (*types.Transaction, error)
+
+ FilterAllowListAdd(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolAllowListAddIterator, error)
+
+ WatchAllowListAdd(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolAllowListAdd) (event.Subscription, error)
+
+ ParseAllowListAdd(log types.Log) (*SiloedLockReleaseTokenPoolAllowListAdd, error)
+
+ FilterAllowListRemove(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolAllowListRemoveIterator, error)
+
+ WatchAllowListRemove(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolAllowListRemove) (event.Subscription, error)
+
+ ParseAllowListRemove(log types.Log) (*SiloedLockReleaseTokenPoolAllowListRemove, error)
+
+ FilterBurned(opts *bind.FilterOpts, sender []common.Address) (*SiloedLockReleaseTokenPoolBurnedIterator, error)
+
+ WatchBurned(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolBurned, sender []common.Address) (event.Subscription, error)
+
+ ParseBurned(log types.Log) (*SiloedLockReleaseTokenPoolBurned, error)
+
+ FilterChainAdded(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainAddedIterator, error)
+
+ WatchChainAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainAdded) (event.Subscription, error)
+
+ ParseChainAdded(log types.Log) (*SiloedLockReleaseTokenPoolChainAdded, error)
+
+ FilterChainConfigured(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainConfiguredIterator, error)
+
+ WatchChainConfigured(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainConfigured) (event.Subscription, error)
+
+ ParseChainConfigured(log types.Log) (*SiloedLockReleaseTokenPoolChainConfigured, error)
+
+ FilterChainRemoved(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainRemovedIterator, error)
+
+ WatchChainRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainRemoved) (event.Subscription, error)
+
+ ParseChainRemoved(log types.Log) (*SiloedLockReleaseTokenPoolChainRemoved, error)
+
+ FilterChainSiloed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainSiloedIterator, error)
+
+ WatchChainSiloed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainSiloed) (event.Subscription, error)
+
+ ParseChainSiloed(log types.Log) (*SiloedLockReleaseTokenPoolChainSiloed, error)
+
+ FilterChainUnsiloed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolChainUnsiloedIterator, error)
+
+ WatchChainUnsiloed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolChainUnsiloed) (event.Subscription, error)
+
+ ParseChainUnsiloed(log types.Log) (*SiloedLockReleaseTokenPoolChainUnsiloed, error)
+
+ FilterConfigChanged(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolConfigChangedIterator, error)
+
+ WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolConfigChanged) (event.Subscription, error)
+
+ ParseConfigChanged(log types.Log) (*SiloedLockReleaseTokenPoolConfigChanged, error)
+
+ FilterLiquidityAdded(opts *bind.FilterOpts, provider []common.Address) (*SiloedLockReleaseTokenPoolLiquidityAddedIterator, error)
+
+ WatchLiquidityAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLiquidityAdded, provider []common.Address) (event.Subscription, error)
+
+ ParseLiquidityAdded(log types.Log) (*SiloedLockReleaseTokenPoolLiquidityAdded, error)
+
+ FilterLiquidityRemoved(opts *bind.FilterOpts, remover []common.Address) (*SiloedLockReleaseTokenPoolLiquidityRemovedIterator, error)
+
+ WatchLiquidityRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLiquidityRemoved, remover []common.Address) (event.Subscription, error)
+
+ ParseLiquidityRemoved(log types.Log) (*SiloedLockReleaseTokenPoolLiquidityRemoved, error)
+
+ FilterLocked(opts *bind.FilterOpts, sender []common.Address) (*SiloedLockReleaseTokenPoolLockedIterator, error)
+
+ WatchLocked(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolLocked, sender []common.Address) (event.Subscription, error)
+
+ ParseLocked(log types.Log) (*SiloedLockReleaseTokenPoolLocked, error)
+
+ FilterMinted(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*SiloedLockReleaseTokenPoolMintedIterator, error)
+
+ WatchMinted(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolMinted, sender []common.Address, recipient []common.Address) (event.Subscription, error)
+
+ ParseMinted(log types.Log) (*SiloedLockReleaseTokenPoolMinted, error)
+
+ FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SiloedLockReleaseTokenPoolOwnershipTransferRequestedIterator, error)
+
+ WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error)
+
+ ParseOwnershipTransferRequested(log types.Log) (*SiloedLockReleaseTokenPoolOwnershipTransferRequested, error)
+
+ FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*SiloedLockReleaseTokenPoolOwnershipTransferredIterator, error)
+
+ WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error)
+
+ ParseOwnershipTransferred(log types.Log) (*SiloedLockReleaseTokenPoolOwnershipTransferred, error)
+
+ FilterRateLimitAdminSet(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolRateLimitAdminSetIterator, error)
+
+ WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRateLimitAdminSet) (event.Subscription, error)
+
+ ParseRateLimitAdminSet(log types.Log) (*SiloedLockReleaseTokenPoolRateLimitAdminSet, error)
+
+ FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*SiloedLockReleaseTokenPoolReleasedIterator, error)
+
+ WatchReleased(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error)
+
+ ParseReleased(log types.Log) (*SiloedLockReleaseTokenPoolReleased, error)
+
+ FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolRemotePoolAddedIterator, error)
+
+ WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error)
+
+ ParseRemotePoolAdded(log types.Log) (*SiloedLockReleaseTokenPoolRemotePoolAdded, error)
+
+ FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolRemotePoolRemovedIterator, error)
+
+ WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error)
+
+ ParseRemotePoolRemoved(log types.Log) (*SiloedLockReleaseTokenPoolRemotePoolRemoved, error)
+
+ FilterRouterUpdated(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolRouterUpdatedIterator, error)
+
+ WatchRouterUpdated(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolRouterUpdated) (event.Subscription, error)
+
+ ParseRouterUpdated(log types.Log) (*SiloedLockReleaseTokenPoolRouterUpdated, error)
+
+ FilterSiloRebalancerSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*SiloedLockReleaseTokenPoolSiloRebalancerSetIterator, error)
+
+ WatchSiloRebalancerSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolSiloRebalancerSet, remoteChainSelector []uint64) (event.Subscription, error)
+
+ ParseSiloRebalancerSet(log types.Log) (*SiloedLockReleaseTokenPoolSiloRebalancerSet, error)
+
+ FilterTokensConsumed(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolTokensConsumedIterator, error)
+
+ WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolTokensConsumed) (event.Subscription, error)
+
+ ParseTokensConsumed(log types.Log) (*SiloedLockReleaseTokenPoolTokensConsumed, error)
+
+ FilterUnsiloedRebalancerSet(opts *bind.FilterOpts) (*SiloedLockReleaseTokenPoolUnsiloedRebalancerSetIterator, error)
+
+ WatchUnsiloedRebalancerSet(opts *bind.WatchOpts, sink chan<- *SiloedLockReleaseTokenPoolUnsiloedRebalancerSet) (event.Subscription, error)
+
+ ParseUnsiloedRebalancerSet(log types.Log) (*SiloedLockReleaseTokenPoolUnsiloedRebalancerSet, error)
+
+ ParseLog(log types.Log) (generated.AbigenLog, error)
+
+ Address() common.Address
+}
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 271347087cc..21e24c90be0 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,15 +1,16 @@
GETH_VERSION: 1.14.11
burn_from_mint_token_pool: ../../../contracts/solc/ccip/BurnFromMintTokenPool/BurnFromMintTokenPool.sol/BurnFromMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnFromMintTokenPool/BurnFromMintTokenPool.sol/BurnFromMintTokenPool.bin ae4e15dc926517092d46e108cd5e24863d58e689444ce310bb00c1390f711ba9
burn_mint_token_pool: ../../../contracts/solc/ccip/BurnMintTokenPool/BurnMintTokenPool.sol/BurnMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnMintTokenPool/BurnMintTokenPool.sol/BurnMintTokenPool.bin 7360dc05306d51b247abdf9a3aa8704847b1f4fb91fdb822a2dfc54e1d86cda1
+burn_to_address_mint_token_pool: ../../../contracts/solc/ccip/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.sol/BurnToAddressMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnToAddressMintTokenPool/BurnToAddressMintTokenPool.sol/BurnToAddressMintTokenPool.bin ca4d24535b7c8a9cff9ca0ff96a41b8410b0e055059e45152e3e49a7c40a6656
burn_with_from_mint_token_pool: ../../../contracts/solc/ccip/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.sol/BurnWithFromMintTokenPool.abi.json ../../../contracts/solc/ccip/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.sol/BurnWithFromMintTokenPool.bin 66715c303bb2da2b49bba100a788f6471b0f94d255d40f92306e279b909ae33b
ccip_encoding_utils: ../../../contracts/solc/ccip/EncodingUtils/EncodingUtils.sol/EncodingUtils.abi.json ../../../contracts/solc/ccip/EncodingUtils/EncodingUtils.sol/EncodingUtils.bin abd960015cec3e4d94a5948d2d66ee915770fe4a744c28a5ff46d23e870baaea
ccip_home: ../../../contracts/solc/ccip/CCIPHome/CCIPHome.sol/CCIPHome.abi.json ../../../contracts/solc/ccip/CCIPHome/CCIPHome.sol/CCIPHome.bin 39de1fbc907a2b573e9358e716803bf5ac3b0a2e622d5bc0069ab60daf38949b
ccip_reader_tester: ../../../contracts/solc/ccip/CCIPReaderTester/CCIPReaderTester.sol/CCIPReaderTester.abi.json ../../../contracts/solc/ccip/CCIPReaderTester/CCIPReaderTester.sol/CCIPReaderTester.bin b8e597d175ec5ff4990d98b4e3b8a8cf06c6ae22977dd6f0e58c0f4107639e8f
ether_sender_receiver: ../../../contracts/solc/ccip/EtherSenderReceiver/EtherSenderReceiver.sol/EtherSenderReceiver.abi.json ../../../contracts/solc/ccip/EtherSenderReceiver/EtherSenderReceiver.sol/EtherSenderReceiver.bin 88973abc1bfbca23a23704e20087ef46f2e20581a13477806308c8f2e664844e
-fee_quoter: ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.abi.json ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.bin 7be986f71fb72d1790b05033ba39531679284ff6a1b8f4978aea11763d932e73
+fee_quoter: ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.abi.json ../../../contracts/solc/ccip/FeeQuoter/FeeQuoter.sol/FeeQuoter.bin 3efd18088f1a27b497ec5b0936f54931e0e151033d5cb32649d497525a3964fa
lock_release_token_pool: ../../../contracts/solc/ccip/LockReleaseTokenPool/LockReleaseTokenPool.sol/LockReleaseTokenPool.abi.json ../../../contracts/solc/ccip/LockReleaseTokenPool/LockReleaseTokenPool.sol/LockReleaseTokenPool.bin 2e73ee0da6f9a9a5722294289b969e4202476706e5d7cdb623e728831c79c28b
log_message_data_receiver: ../../../contracts/solc/ccip/LogMessageDataReceiver/LogMessageDataReceiver.sol/LogMessageDataReceiver.abi.json ../../../contracts/solc/ccip/LogMessageDataReceiver/LogMessageDataReceiver.sol/LogMessageDataReceiver.bin 6fe60e48711884eae82dd95cabb1c66a5644336719fa1219df1ceceec11e6bce
-maybe_revert_message_receiver: ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.abi.json ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.bin d1eb951af1027ca20cbee2c34df80fddbfd861e1695989aeebd29327cfe56584
+maybe_revert_message_receiver: ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.abi.json ../../../contracts/solc/ccip/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.sol/MaybeRevertMessageReceiver.bin ee264f67a2356cc4eebe839a5a88367cbcdc27a7520cca56263319e9afe97a1a
message_hasher: ../../../contracts/solc/ccip/MessageHasher/MessageHasher.sol/MessageHasher.abi.json ../../../contracts/solc/ccip/MessageHasher/MessageHasher.sol/MessageHasher.bin ada9824b9e506bb9619e4e16657631cf87a3a6008f8586beff2893bfe46b0055
mock_usdc_token_messenger: ../../../contracts/solc/ccip/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.sol/MockE2EUSDCTokenMessenger.abi.json ../../../contracts/solc/ccip/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.sol/MockE2EUSDCTokenMessenger.bin ad7902d63667e582b93b2fad139aa53111f9fddcedf92b1d6d122d1ab7ec4bab
mock_usdc_token_transmitter: ../../../contracts/solc/ccip/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.sol/MockE2EUSDCTransmitter.abi.json ../../../contracts/solc/ccip/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.sol/MockE2EUSDCTransmitter.bin ae0d090105bc248f4eccd337836ec1db760c506d6f5578e662305abbbc520fcd
@@ -27,8 +28,8 @@ rmn_home: ../../../contracts/solc/ccip/RMNHome/RMNHome.sol/RMNHome.abi.json ../.
rmn_proxy_contract: ../../../contracts/solc/ccip/RMNProxy/RMNProxy.sol/RMNProxy.abi.json ../../../contracts/solc/ccip/RMNProxy/RMNProxy.sol/RMNProxy.bin 4d06f9e5c6f72daef745e6114faed3bae57ad29758d75de5a4eefcd5f0172328
rmn_remote: ../../../contracts/solc/ccip/RMNRemote/RMNRemote.sol/RMNRemote.abi.json ../../../contracts/solc/ccip/RMNRemote/RMNRemote.sol/RMNRemote.bin 32173df61397fc104bc6bcd9d8e929165ee3911518350dc7f2bb5d1d94875a94
router: ../../../contracts/solc/ccip/Router/Router.sol/Router.abi.json ../../../contracts/solc/ccip/Router/Router.sol/Router.bin 0103ab2fd344179d49f0320d0a47ec8255fe8a401a2f2c8973e8314dc49d2413
+siloed_lock_release_token_pool: ../../../contracts/solc/ccip/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.sol/SiloedLockReleaseTokenPool.abi.json ../../../contracts/solc/ccip/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.sol/SiloedLockReleaseTokenPool.bin 53a592f99d2a47e0b9b012d6f863a0224ba106b687511ff6c67cea160c42fc3a
token_admin_registry: ../../../contracts/solc/ccip/TokenAdminRegistry/TokenAdminRegistry.sol/TokenAdminRegistry.abi.json ../../../contracts/solc/ccip/TokenAdminRegistry/TokenAdminRegistry.sol/TokenAdminRegistry.bin 086268b9df56e089a69a96ce3e4fd03a07a00a1c8812ba9504e31930a5c3ff1d
token_pool: ../../../contracts/solc/ccip/TokenPool/TokenPool.sol/TokenPool.abi.json ../../../contracts/solc/ccip/TokenPool/TokenPool.sol/TokenPool.bin 6c00ce7b2082f40d5f9b4808eb692a90e81c312b4f5d70d62e4b1ef69a164a9f
usdc_reader_tester: ../../../contracts/solc/ccip/USDCReaderTester/USDCReaderTester.sol/USDCReaderTester.abi.json ../../../contracts/solc/ccip/USDCReaderTester/USDCReaderTester.sol/USDCReaderTester.bin 7622b1e42bc9c3933c51607d765d8463796c615155596929e554a58ed68b263d
usdc_token_pool: ../../../contracts/solc/ccip/USDCTokenPool/USDCTokenPool.sol/USDCTokenPool.abi.json ../../../contracts/solc/ccip/USDCTokenPool/USDCTokenPool.sol/USDCTokenPool.bin 8a44f8d2d193fc1332e5e80a5e05172dc15680e0921d7cc945ea321746f764fc
-weth9: ../../../contracts/solc/ccip/WETH9/WETH9.sol/WETH9.abi.json ../../../contracts/solc/ccip/WETH9/WETH9.sol/WETH9.bin 89ee9892414b4d9abfb18046504aa7771c88c52a0831479ca4152f120e647d49
diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go
index 7061cca9a33..734789f338f 100644
--- a/core/gethwrappers/ccip/go_generate.go
+++ b/core/gethwrappers/ccip/go_generate.go
@@ -22,6 +22,8 @@ package ccip
//go:generate go run ../generation/wrap.go ccip LockReleaseTokenPool lock_release_token_pool
//go:generate go run ../generation/wrap.go ccip TokenPool token_pool
//go:generate go run ../generation/wrap.go ccip USDCTokenPool usdc_token_pool
+//go:generate go run ../generation/wrap.go ccip SiloedLockReleaseTokenPool siloed_lock_release_token_pool
+//go:generate go run ../generation/wrap.go ccip BurnToAddressMintTokenPool burn_to_address_mint_token_pool
// Helpers
//go:generate go run ../generation/wrap.go ccip MaybeRevertMessageReceiver maybe_revert_message_receiver
@@ -32,7 +34,6 @@ package ccip
//go:generate go run ../generation/wrap.go ccip USDCReaderTester usdc_reader_tester
//go:generate go run ../generation/wrap.go ccip ReportCodec report_codec
//go:generate go run ../generation/wrap.go ccip EtherSenderReceiver ether_sender_receiver
-//go:generate go run ../generation/wrap.go ccip WETH9 weth9
//go:generate go run ../generation/wrap.go ccip MockE2EUSDCTokenMessenger mock_usdc_token_messenger
//go:generate go run ../generation/wrap.go ccip MockE2EUSDCTransmitter mock_usdc_token_transmitter
//go:generate go run ../generation/wrap.go ccip CCIPReaderTester ccip_reader_tester
diff --git a/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go b/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go
deleted file mode 100644
index 87849c786f4..00000000000
--- a/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go
+++ /dev/null
@@ -1,1010 +0,0 @@
-// Code generated - DO NOT EDIT.
-// This file is a generated binding and any manual changes will be lost.
-
-package weth9_wrapper
-
-import (
- "errors"
- "fmt"
- "math/big"
- "strings"
-
- ethereum "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/event"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
-)
-
-var (
- _ = errors.New
- _ = big.NewInt
- _ = strings.NewReader
- _ = ethereum.NotFound
- _ = bind.Bind
- _ = common.Big1
- _ = types.BloomLookup
- _ = event.NewSubscription
- _ = abi.ConvertType
-)
-
-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: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610114565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610114565b506002805460ff1916601217905534801561006f57600080fd5b506101d3565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561010f57600081815260208120601f850160051c810160208610156100ec5750805b601f850160051c820191505b8181101561010b578281556001016100f8565b5050505b505050565b81516001600160401b0381111561012d5761012d610075565b6101418161013b845461008b565b846100c5565b602080601f831160018114610176576000841561015e5750858301515b600019600386901b1c1916600185901b17855561010b565b600085815260208120601f198616915b828110156101a557888601518255948401946001909101908401610186565b50858210156101c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6109b680620001e36000396000f3fe6080604052600436106100cb5760003560e01c806340c10f1911610074578063a9059cbb1161004e578063a9059cbb14610225578063d0e30db014610245578063dd62ed3e1461024d57600080fd5b806340c10f19146101c357806370a08231146101e357806395d89b411461021057600080fd5b806323b872dd116100a557806323b872dd146101575780632e1a7d4d14610177578063313ce5671461019757600080fd5b806306fdde03146100df578063095ea7b31461010a57806318160ddd1461013a57600080fd5b366100da576100d8610285565b005b600080fd5b3480156100eb57600080fd5b506100f46102e0565b604051610101919061079f565b60405180910390f35b34801561011657600080fd5b5061012a610125366004610834565b61036e565b6040519015158152602001610101565b34801561014657600080fd5b50475b604051908152602001610101565b34801561016357600080fd5b5061012a61017236600461085e565b6103e8565b34801561018357600080fd5b506100d861019236600461089a565b610649565b3480156101a357600080fd5b506002546101b19060ff1681565b60405160ff9091168152602001610101565b3480156101cf57600080fd5b506100d86101de366004610834565b610736565b3480156101ef57600080fd5b506101496101fe3660046108b3565b60036020526000908152604090205481565b34801561021c57600080fd5b506100f4610774565b34801561023157600080fd5b5061012a610240366004610834565b610781565b6100d8610795565b34801561025957600080fd5b506101496102683660046108ce565b600460209081526000928352604080842090915290825290205481565b33600090815260036020526040812080543492906102a4908490610930565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102ed90610943565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610943565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103d69086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054821115610447576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104ad575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156105625773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561051c576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091528120805484929061055c908490610996565b90915550505b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604081208054849290610597908490610996565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080548492906105d1908490610930565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161063791815260200190565b60405180910390a35060019392505050565b33600090815260036020526040902054811115610692576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260036020526040812080548392906106b1908490610996565b909155505060405133908290600081818185875af1925050503d80600081146106f6576040519150601f19603f3d011682016040523d82523d6000602084013e6106fb565b606091505b50506040518281523391507f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061076b908490610930565b90915550505050565b600180546102ed90610943565b600061078e3384846103e8565b9392505050565b61079d610285565b565b600060208083528351808285015260005b818110156107cc578581018301518582016040015282016107b0565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461082f57600080fd5b919050565b6000806040838503121561084757600080fd5b6108508361080b565b946020939093013593505050565b60008060006060848603121561087357600080fd5b61087c8461080b565b925061088a6020850161080b565b9150604084013590509250925092565b6000602082840312156108ac57600080fd5b5035919050565b6000602082840312156108c557600080fd5b61078e8261080b565b600080604083850312156108e157600080fd5b6108ea8361080b565b91506108f86020840161080b565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103e2576103e2610901565b600181811c9082168061095757607f821691505b602082108103610990577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103e2576103e261090156fea164736f6c6343000813000a",
-}
-
-var WETH9ABI = WETH9MetaData.ABI
-
-var WETH9Bin = WETH9MetaData.Bin
-
-func DeployWETH9(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *WETH9, error) {
- parsed, err := WETH9MetaData.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(WETH9Bin), backend)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &WETH9{address: address, abi: *parsed, WETH9Caller: WETH9Caller{contract: contract}, WETH9Transactor: WETH9Transactor{contract: contract}, WETH9Filterer: WETH9Filterer{contract: contract}}, nil
-}
-
-type WETH9 struct {
- address common.Address
- abi abi.ABI
- WETH9Caller
- WETH9Transactor
- WETH9Filterer
-}
-
-type WETH9Caller struct {
- contract *bind.BoundContract
-}
-
-type WETH9Transactor struct {
- contract *bind.BoundContract
-}
-
-type WETH9Filterer struct {
- contract *bind.BoundContract
-}
-
-type WETH9Session struct {
- Contract *WETH9
- CallOpts bind.CallOpts
- TransactOpts bind.TransactOpts
-}
-
-type WETH9CallerSession struct {
- Contract *WETH9Caller
- CallOpts bind.CallOpts
-}
-
-type WETH9TransactorSession struct {
- Contract *WETH9Transactor
- TransactOpts bind.TransactOpts
-}
-
-type WETH9Raw struct {
- Contract *WETH9
-}
-
-type WETH9CallerRaw struct {
- Contract *WETH9Caller
-}
-
-type WETH9TransactorRaw struct {
- Contract *WETH9Transactor
-}
-
-func NewWETH9(address common.Address, backend bind.ContractBackend) (*WETH9, error) {
- abi, err := abi.JSON(strings.NewReader(WETH9ABI))
- if err != nil {
- return nil, err
- }
- contract, err := bindWETH9(address, backend, backend, backend)
- if err != nil {
- return nil, err
- }
- return &WETH9{address: address, abi: abi, WETH9Caller: WETH9Caller{contract: contract}, WETH9Transactor: WETH9Transactor{contract: contract}, WETH9Filterer: WETH9Filterer{contract: contract}}, nil
-}
-
-func NewWETH9Caller(address common.Address, caller bind.ContractCaller) (*WETH9Caller, error) {
- contract, err := bindWETH9(address, caller, nil, nil)
- if err != nil {
- return nil, err
- }
- return &WETH9Caller{contract: contract}, nil
-}
-
-func NewWETH9Transactor(address common.Address, transactor bind.ContractTransactor) (*WETH9Transactor, error) {
- contract, err := bindWETH9(address, nil, transactor, nil)
- if err != nil {
- return nil, err
- }
- return &WETH9Transactor{contract: contract}, nil
-}
-
-func NewWETH9Filterer(address common.Address, filterer bind.ContractFilterer) (*WETH9Filterer, error) {
- contract, err := bindWETH9(address, nil, nil, filterer)
- if err != nil {
- return nil, err
- }
- return &WETH9Filterer{contract: contract}, nil
-}
-
-func bindWETH9(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
- parsed, err := WETH9MetaData.GetAbi()
- if err != nil {
- return nil, err
- }
- return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
-}
-
-func (_WETH9 *WETH9Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
- return _WETH9.Contract.WETH9Caller.contract.Call(opts, result, method, params...)
-}
-
-func (_WETH9 *WETH9Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _WETH9.Contract.WETH9Transactor.contract.Transfer(opts)
-}
-
-func (_WETH9 *WETH9Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _WETH9.Contract.WETH9Transactor.contract.Transact(opts, method, params...)
-}
-
-func (_WETH9 *WETH9CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
- return _WETH9.Contract.contract.Call(opts, result, method, params...)
-}
-
-func (_WETH9 *WETH9TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _WETH9.Contract.contract.Transfer(opts)
-}
-
-func (_WETH9 *WETH9TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _WETH9.Contract.contract.Transact(opts, method, params...)
-}
-
-func (_WETH9 *WETH9Caller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "allowance", arg0, arg1)
-
- if err != nil {
- return *new(*big.Int), err
- }
-
- out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) {
- return _WETH9.Contract.Allowance(&_WETH9.CallOpts, arg0, arg1)
-}
-
-func (_WETH9 *WETH9CallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) {
- return _WETH9.Contract.Allowance(&_WETH9.CallOpts, arg0, arg1)
-}
-
-func (_WETH9 *WETH9Caller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "balanceOf", arg0)
-
- if err != nil {
- return *new(*big.Int), err
- }
-
- out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) BalanceOf(arg0 common.Address) (*big.Int, error) {
- return _WETH9.Contract.BalanceOf(&_WETH9.CallOpts, arg0)
-}
-
-func (_WETH9 *WETH9CallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) {
- return _WETH9.Contract.BalanceOf(&_WETH9.CallOpts, arg0)
-}
-
-func (_WETH9 *WETH9Caller) Decimals(opts *bind.CallOpts) (uint8, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "decimals")
-
- if err != nil {
- return *new(uint8), err
- }
-
- out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) Decimals() (uint8, error) {
- return _WETH9.Contract.Decimals(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9CallerSession) Decimals() (uint8, error) {
- return _WETH9.Contract.Decimals(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9Caller) Name(opts *bind.CallOpts) (string, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "name")
-
- if err != nil {
- return *new(string), err
- }
-
- out0 := *abi.ConvertType(out[0], new(string)).(*string)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) Name() (string, error) {
- return _WETH9.Contract.Name(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9CallerSession) Name() (string, error) {
- return _WETH9.Contract.Name(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9Caller) Symbol(opts *bind.CallOpts) (string, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "symbol")
-
- if err != nil {
- return *new(string), err
- }
-
- out0 := *abi.ConvertType(out[0], new(string)).(*string)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) Symbol() (string, error) {
- return _WETH9.Contract.Symbol(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9CallerSession) Symbol() (string, error) {
- return _WETH9.Contract.Symbol(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) {
- var out []interface{}
- err := _WETH9.contract.Call(opts, &out, "totalSupply")
-
- if err != nil {
- return *new(*big.Int), err
- }
-
- out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
-
- return out0, err
-
-}
-
-func (_WETH9 *WETH9Session) TotalSupply() (*big.Int, error) {
- return _WETH9.Contract.TotalSupply(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9CallerSession) TotalSupply() (*big.Int, error) {
- return _WETH9.Contract.TotalSupply(&_WETH9.CallOpts)
-}
-
-func (_WETH9 *WETH9Transactor) Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "approve", guy, wad)
-}
-
-func (_WETH9 *WETH9Session) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Approve(&_WETH9.TransactOpts, guy, wad)
-}
-
-func (_WETH9 *WETH9TransactorSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Approve(&_WETH9.TransactOpts, guy, wad)
-}
-
-func (_WETH9 *WETH9Transactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "deposit")
-}
-
-func (_WETH9 *WETH9Session) Deposit() (*types.Transaction, error) {
- return _WETH9.Contract.Deposit(&_WETH9.TransactOpts)
-}
-
-func (_WETH9 *WETH9TransactorSession) Deposit() (*types.Transaction, error) {
- return _WETH9.Contract.Deposit(&_WETH9.TransactOpts)
-}
-
-func (_WETH9 *WETH9Transactor) Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "mint", account, amount)
-}
-
-func (_WETH9 *WETH9Session) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Mint(&_WETH9.TransactOpts, account, amount)
-}
-
-func (_WETH9 *WETH9TransactorSession) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Mint(&_WETH9.TransactOpts, account, amount)
-}
-
-func (_WETH9 *WETH9Transactor) Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "transfer", dst, wad)
-}
-
-func (_WETH9 *WETH9Session) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Transfer(&_WETH9.TransactOpts, dst, wad)
-}
-
-func (_WETH9 *WETH9TransactorSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Transfer(&_WETH9.TransactOpts, dst, wad)
-}
-
-func (_WETH9 *WETH9Transactor) TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "transferFrom", src, dst, wad)
-}
-
-func (_WETH9 *WETH9Session) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.TransferFrom(&_WETH9.TransactOpts, src, dst, wad)
-}
-
-func (_WETH9 *WETH9TransactorSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.TransferFrom(&_WETH9.TransactOpts, src, dst, wad)
-}
-
-func (_WETH9 *WETH9Transactor) Withdraw(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error) {
- return _WETH9.contract.Transact(opts, "withdraw", wad)
-}
-
-func (_WETH9 *WETH9Session) Withdraw(wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Withdraw(&_WETH9.TransactOpts, wad)
-}
-
-func (_WETH9 *WETH9TransactorSession) Withdraw(wad *big.Int) (*types.Transaction, error) {
- return _WETH9.Contract.Withdraw(&_WETH9.TransactOpts, wad)
-}
-
-func (_WETH9 *WETH9Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _WETH9.contract.RawTransact(opts, nil)
-}
-
-func (_WETH9 *WETH9Session) Receive() (*types.Transaction, error) {
- return _WETH9.Contract.Receive(&_WETH9.TransactOpts)
-}
-
-func (_WETH9 *WETH9TransactorSession) Receive() (*types.Transaction, error) {
- return _WETH9.Contract.Receive(&_WETH9.TransactOpts)
-}
-
-type WETH9ApprovalIterator struct {
- Event *WETH9Approval
-
- contract *bind.BoundContract
- event string
-
- logs chan types.Log
- sub ethereum.Subscription
- done bool
- fail error
-}
-
-func (it *WETH9ApprovalIterator) Next() bool {
-
- if it.fail != nil {
- return false
- }
-
- if it.done {
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Approval)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- default:
- return false
- }
- }
-
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Approval)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- case err := <-it.sub.Err():
- it.done = true
- it.fail = err
- return it.Next()
- }
-}
-
-func (it *WETH9ApprovalIterator) Error() error {
- return it.fail
-}
-
-func (it *WETH9ApprovalIterator) Close() error {
- it.sub.Unsubscribe()
- return nil
-}
-
-type WETH9Approval struct {
- Src common.Address
- Guy common.Address
- Wad *big.Int
- Raw types.Log
-}
-
-func (_WETH9 *WETH9Filterer) FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*WETH9ApprovalIterator, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
- var guyRule []interface{}
- for _, guyItem := range guy {
- guyRule = append(guyRule, guyItem)
- }
-
- logs, sub, err := _WETH9.contract.FilterLogs(opts, "Approval", srcRule, guyRule)
- if err != nil {
- return nil, err
- }
- return &WETH9ApprovalIterator{contract: _WETH9.contract, event: "Approval", logs: logs, sub: sub}, nil
-}
-
-func (_WETH9 *WETH9Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *WETH9Approval, src []common.Address, guy []common.Address) (event.Subscription, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
- var guyRule []interface{}
- for _, guyItem := range guy {
- guyRule = append(guyRule, guyItem)
- }
-
- logs, sub, err := _WETH9.contract.WatchLogs(opts, "Approval", srcRule, guyRule)
- if err != nil {
- return nil, err
- }
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case log := <-logs:
-
- event := new(WETH9Approval)
- if err := _WETH9.contract.UnpackLog(event, "Approval", log); err != nil {
- return err
- }
- event.Raw = log
-
- select {
- case sink <- event:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-func (_WETH9 *WETH9Filterer) ParseApproval(log types.Log) (*WETH9Approval, error) {
- event := new(WETH9Approval)
- if err := _WETH9.contract.UnpackLog(event, "Approval", log); err != nil {
- return nil, err
- }
- event.Raw = log
- return event, nil
-}
-
-type WETH9DepositIterator struct {
- Event *WETH9Deposit
-
- contract *bind.BoundContract
- event string
-
- logs chan types.Log
- sub ethereum.Subscription
- done bool
- fail error
-}
-
-func (it *WETH9DepositIterator) Next() bool {
-
- if it.fail != nil {
- return false
- }
-
- if it.done {
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Deposit)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- default:
- return false
- }
- }
-
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Deposit)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- case err := <-it.sub.Err():
- it.done = true
- it.fail = err
- return it.Next()
- }
-}
-
-func (it *WETH9DepositIterator) Error() error {
- return it.fail
-}
-
-func (it *WETH9DepositIterator) Close() error {
- it.sub.Unsubscribe()
- return nil
-}
-
-type WETH9Deposit struct {
- Dst common.Address
- Wad *big.Int
- Raw types.Log
-}
-
-func (_WETH9 *WETH9Filterer) FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*WETH9DepositIterator, error) {
-
- var dstRule []interface{}
- for _, dstItem := range dst {
- dstRule = append(dstRule, dstItem)
- }
-
- logs, sub, err := _WETH9.contract.FilterLogs(opts, "Deposit", dstRule)
- if err != nil {
- return nil, err
- }
- return &WETH9DepositIterator{contract: _WETH9.contract, event: "Deposit", logs: logs, sub: sub}, nil
-}
-
-func (_WETH9 *WETH9Filterer) WatchDeposit(opts *bind.WatchOpts, sink chan<- *WETH9Deposit, dst []common.Address) (event.Subscription, error) {
-
- var dstRule []interface{}
- for _, dstItem := range dst {
- dstRule = append(dstRule, dstItem)
- }
-
- logs, sub, err := _WETH9.contract.WatchLogs(opts, "Deposit", dstRule)
- if err != nil {
- return nil, err
- }
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case log := <-logs:
-
- event := new(WETH9Deposit)
- if err := _WETH9.contract.UnpackLog(event, "Deposit", log); err != nil {
- return err
- }
- event.Raw = log
-
- select {
- case sink <- event:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-func (_WETH9 *WETH9Filterer) ParseDeposit(log types.Log) (*WETH9Deposit, error) {
- event := new(WETH9Deposit)
- if err := _WETH9.contract.UnpackLog(event, "Deposit", log); err != nil {
- return nil, err
- }
- event.Raw = log
- return event, nil
-}
-
-type WETH9TransferIterator struct {
- Event *WETH9Transfer
-
- contract *bind.BoundContract
- event string
-
- logs chan types.Log
- sub ethereum.Subscription
- done bool
- fail error
-}
-
-func (it *WETH9TransferIterator) Next() bool {
-
- if it.fail != nil {
- return false
- }
-
- if it.done {
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Transfer)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- default:
- return false
- }
- }
-
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Transfer)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- case err := <-it.sub.Err():
- it.done = true
- it.fail = err
- return it.Next()
- }
-}
-
-func (it *WETH9TransferIterator) Error() error {
- return it.fail
-}
-
-func (it *WETH9TransferIterator) Close() error {
- it.sub.Unsubscribe()
- return nil
-}
-
-type WETH9Transfer struct {
- Src common.Address
- Dst common.Address
- Wad *big.Int
- Raw types.Log
-}
-
-func (_WETH9 *WETH9Filterer) FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*WETH9TransferIterator, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
- var dstRule []interface{}
- for _, dstItem := range dst {
- dstRule = append(dstRule, dstItem)
- }
-
- logs, sub, err := _WETH9.contract.FilterLogs(opts, "Transfer", srcRule, dstRule)
- if err != nil {
- return nil, err
- }
- return &WETH9TransferIterator{contract: _WETH9.contract, event: "Transfer", logs: logs, sub: sub}, nil
-}
-
-func (_WETH9 *WETH9Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *WETH9Transfer, src []common.Address, dst []common.Address) (event.Subscription, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
- var dstRule []interface{}
- for _, dstItem := range dst {
- dstRule = append(dstRule, dstItem)
- }
-
- logs, sub, err := _WETH9.contract.WatchLogs(opts, "Transfer", srcRule, dstRule)
- if err != nil {
- return nil, err
- }
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case log := <-logs:
-
- event := new(WETH9Transfer)
- if err := _WETH9.contract.UnpackLog(event, "Transfer", log); err != nil {
- return err
- }
- event.Raw = log
-
- select {
- case sink <- event:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-func (_WETH9 *WETH9Filterer) ParseTransfer(log types.Log) (*WETH9Transfer, error) {
- event := new(WETH9Transfer)
- if err := _WETH9.contract.UnpackLog(event, "Transfer", log); err != nil {
- return nil, err
- }
- event.Raw = log
- return event, nil
-}
-
-type WETH9WithdrawalIterator struct {
- Event *WETH9Withdrawal
-
- contract *bind.BoundContract
- event string
-
- logs chan types.Log
- sub ethereum.Subscription
- done bool
- fail error
-}
-
-func (it *WETH9WithdrawalIterator) Next() bool {
-
- if it.fail != nil {
- return false
- }
-
- if it.done {
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Withdrawal)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- default:
- return false
- }
- }
-
- select {
- case log := <-it.logs:
- it.Event = new(WETH9Withdrawal)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- case err := <-it.sub.Err():
- it.done = true
- it.fail = err
- return it.Next()
- }
-}
-
-func (it *WETH9WithdrawalIterator) Error() error {
- return it.fail
-}
-
-func (it *WETH9WithdrawalIterator) Close() error {
- it.sub.Unsubscribe()
- return nil
-}
-
-type WETH9Withdrawal struct {
- Src common.Address
- Wad *big.Int
- Raw types.Log
-}
-
-func (_WETH9 *WETH9Filterer) FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*WETH9WithdrawalIterator, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
-
- logs, sub, err := _WETH9.contract.FilterLogs(opts, "Withdrawal", srcRule)
- if err != nil {
- return nil, err
- }
- return &WETH9WithdrawalIterator{contract: _WETH9.contract, event: "Withdrawal", logs: logs, sub: sub}, nil
-}
-
-func (_WETH9 *WETH9Filterer) WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *WETH9Withdrawal, src []common.Address) (event.Subscription, error) {
-
- var srcRule []interface{}
- for _, srcItem := range src {
- srcRule = append(srcRule, srcItem)
- }
-
- logs, sub, err := _WETH9.contract.WatchLogs(opts, "Withdrawal", srcRule)
- if err != nil {
- return nil, err
- }
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case log := <-logs:
-
- event := new(WETH9Withdrawal)
- if err := _WETH9.contract.UnpackLog(event, "Withdrawal", log); err != nil {
- return err
- }
- event.Raw = log
-
- select {
- case sink <- event:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-func (_WETH9 *WETH9Filterer) ParseWithdrawal(log types.Log) (*WETH9Withdrawal, error) {
- event := new(WETH9Withdrawal)
- if err := _WETH9.contract.UnpackLog(event, "Withdrawal", log); err != nil {
- return nil, err
- }
- event.Raw = log
- return event, nil
-}
-
-func (_WETH9 *WETH9) ParseLog(log types.Log) (generated.AbigenLog, error) {
- switch log.Topics[0] {
- case _WETH9.abi.Events["Approval"].ID:
- return _WETH9.ParseApproval(log)
- case _WETH9.abi.Events["Deposit"].ID:
- return _WETH9.ParseDeposit(log)
- case _WETH9.abi.Events["Transfer"].ID:
- return _WETH9.ParseTransfer(log)
- case _WETH9.abi.Events["Withdrawal"].ID:
- return _WETH9.ParseWithdrawal(log)
-
- default:
- return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0])
- }
-}
-
-func (WETH9Approval) Topic() common.Hash {
- return common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925")
-}
-
-func (WETH9Deposit) Topic() common.Hash {
- return common.HexToHash("0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c")
-}
-
-func (WETH9Transfer) Topic() common.Hash {
- return common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
-}
-
-func (WETH9Withdrawal) Topic() common.Hash {
- return common.HexToHash("0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65")
-}
-
-func (_WETH9 *WETH9) Address() common.Address {
- return _WETH9.address
-}
-
-type WETH9Interface interface {
- Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error)
-
- BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error)
-
- Decimals(opts *bind.CallOpts) (uint8, error)
-
- Name(opts *bind.CallOpts) (string, error)
-
- Symbol(opts *bind.CallOpts) (string, error)
-
- TotalSupply(opts *bind.CallOpts) (*big.Int, error)
-
- Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error)
-
- Deposit(opts *bind.TransactOpts) (*types.Transaction, error)
-
- Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error)
-
- Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error)
-
- TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error)
-
- Withdraw(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error)
-
- Receive(opts *bind.TransactOpts) (*types.Transaction, error)
-
- FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*WETH9ApprovalIterator, error)
-
- WatchApproval(opts *bind.WatchOpts, sink chan<- *WETH9Approval, src []common.Address, guy []common.Address) (event.Subscription, error)
-
- ParseApproval(log types.Log) (*WETH9Approval, error)
-
- FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*WETH9DepositIterator, error)
-
- WatchDeposit(opts *bind.WatchOpts, sink chan<- *WETH9Deposit, dst []common.Address) (event.Subscription, error)
-
- ParseDeposit(log types.Log) (*WETH9Deposit, error)
-
- FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*WETH9TransferIterator, error)
-
- WatchTransfer(opts *bind.WatchOpts, sink chan<- *WETH9Transfer, src []common.Address, dst []common.Address) (event.Subscription, error)
-
- ParseTransfer(log types.Log) (*WETH9Transfer, error)
-
- FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*WETH9WithdrawalIterator, error)
-
- WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *WETH9Withdrawal, src []common.Address) (event.Subscription, error)
-
- ParseWithdrawal(log types.Log) (*WETH9Withdrawal, error)
-
- ParseLog(log types.Log) (generated.AbigenLog, error)
-
- Address() common.Address
-}
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 7080ec31b26..3469f5ef4a2 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
@@ -117,4 +117,3 @@ 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 393b7b1ea2d1dc5a520a60cc6736dc489726cb0bd1481ea8b22d2872d4a510b1
diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go
index 7f1d3f02e91..339c27d98d5 100644
--- a/core/gethwrappers/go_generate.go
+++ b/core/gethwrappers/go_generate.go
@@ -57,7 +57,6 @@ package gethwrappers
//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
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.abi ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.bin MockETHUSDAggregator mock_ethusd_aggregator_wrapper
-//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/WETH9/WETH9.abi ../../contracts/solc/v0.8.19/WETH9/WETH9.bin WETH9 weth9_wrapper
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin ILogAutomation i_log_automation
//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin AutomationForwarderLogic automation_forwarder_logic
diff --git a/core/gethwrappers/ccip/generated/weth9/weth9.go b/core/gethwrappers/shared/generated/weth9/weth9.go
similarity index 83%
rename from core/gethwrappers/ccip/generated/weth9/weth9.go
rename to core/gethwrappers/shared/generated/weth9/weth9.go
index 34c1fd7fb8b..f8c1c3e157b 100644
--- a/core/gethwrappers/ccip/generated/weth9/weth9.go
+++ b/core/gethwrappers/shared/generated/weth9/weth9.go
@@ -32,7 +32,7 @@ var (
var WETH9MetaData = &bind.MetaData{
ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"guy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]",
- Bin: "0x60806040523461011457610014600054610119565b601f81116100cb575b507f577261707065642045746865720000000000000000000000000000000000001a60005560015461004e90610119565b601f8111610081575b6008630ae8aa8960e31b016001556002805460ff19166012179055604051610a5a90816101548239f35b6001600052601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101905b8181106100bf5750610057565b600081556001016100b2565b60008052601f0160051c7f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563908101905b818110610108575061001d565b600081556001016100fb565b600080fd5b90600182811c92168015610149575b602083101461013357565b634e487b7160e01b600052602260045260246000fd5b91607f169161012856fe60806040526004361015610062575b361561001957600080fd5b33600052600360205260406000206100323482546108a0565b90556040513481527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2005b60003560e01c806306fdde0314610696578063095ea7b3146105ef57806318160ddd146105b557806323b872dd146105685780632e1a7d4d146104aa578063313ce5671461046b57806370a082311461040657806395d89b4114610208578063a9059cbb146101b8578063d0e30db0146101755763dd62ed3e0361000e57346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761011761081e565b73ffffffffffffffffffffffffffffffffffffffff610134610841565b9116600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b600080fd5b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705733600052600360205260406000206100323482546108a0565b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6101f461081e565b60243590336108ad565b6040519015158152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610170576000604051908091600154928360011c600185169485156103fc575b6020821086146103cf57839495828552908160001461036f57506001146102f6575b5003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b0390f35b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600185528491507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061035357505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261031f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b840190910191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09050610275565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b90607f1690610253565b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705773ffffffffffffffffffffffffffffffffffffffff61045261081e565b1660005260036020526020604060002054604051908152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602060ff60025416604051908152f35b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057600435336000526003602052806040600020541061017057336000526003602052604060002061050a828254610864565b9055806000811561055f575b600080809381933390f115610553576040519081527f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b6560203392a2005b6040513d6000823e3d90fd5b506108fc610516565b346101705760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6105a461081e565b6105ac610841565b604435916108ad565b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602047604051908152f35b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761062661081e565b73ffffffffffffffffffffffffffffffffffffffff6024359133600052600460205260406000208282166000526020528260406000205560405192835216907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760006040519080918154928360011c600185169485156107ac575b6020821086146103cf57839495828552908160001461036f5750600114610751575003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b848052602085208592505b81831061079057505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261075c565b90607f16906106e0565b9190916020815282519283602083015260005b8481106108085750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b80602080928401015160408286010152016107c9565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b9190820391821161087157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820180921161087157565b73ffffffffffffffffffffffffffffffffffffffff16908160005260036020528260406000205410610170573382141580610a03575b610963575b602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600383526040600020610939878254610864565b90551693846000526003825260406000206109558282546108a0565b9055604051908152a3600190565b816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff3316600052602052826040600020541061017057602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600483526040600020823316600052835260406000206109f8878254610864565b9055925050506108e8565b50816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff33166000526020526fffffffffffffffffffffffffffffffff60406000205414156108e356fea164736f6c634300081a000a",
+ Bin: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610114565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610114565b506002805460ff1916601217905534801561006f57600080fd5b506101d3565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561010f57600081815260208120601f850160051c810160208610156100ec5750805b601f850160051c820191505b8181101561010b578281556001016100f8565b5050505b505050565b81516001600160401b0381111561012d5761012d610075565b6101418161013b845461008b565b846100c5565b602080601f831160018114610176576000841561015e5750858301515b600019600386901b1c1916600185901b17855561010b565b600085815260208120601f198616915b828110156101a557888601518255948401946001909101908401610186565b50858210156101c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6108ac806101e26000396000f3fe6080604052600436106100c05760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146101fa578063d0e30db01461021a578063dd62ed3e1461022257600080fd5b8063313ce5671461018c57806370a08231146101b857806395d89b41146101e557600080fd5b806318160ddd116100a557806318160ddd1461012f57806323b872dd1461014c5780632e1a7d4d1461016c57600080fd5b806306fdde03146100d4578063095ea7b3146100ff57600080fd5b366100cf576100cd61025a565b005b600080fd5b3480156100e057600080fd5b506100e96102b5565b6040516100f69190610695565b60405180910390f35b34801561010b57600080fd5b5061011f61011a36600461072a565b610343565b60405190151581526020016100f6565b34801561013b57600080fd5b50475b6040519081526020016100f6565b34801561015857600080fd5b5061011f610167366004610754565b6103bd565b34801561017857600080fd5b506100cd610187366004610790565b6105c4565b34801561019857600080fd5b506002546101a69060ff1681565b60405160ff90911681526020016100f6565b3480156101c457600080fd5b5061013e6101d33660046107a9565b60036020526000908152604090205481565b3480156101f157600080fd5b506100e961066a565b34801561020657600080fd5b5061011f61021536600461072a565b610677565b6100cd61068b565b34801561022e57600080fd5b5061013e61023d3660046107c4565b600460209081526000928352604080842090915290825290205481565b3360009081526003602052604081208054349290610279908490610826565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102c290610839565b80601f01602080910402602001604051908101604052809291908181526020018280546102ee90610839565b801561033b5780601f106103105761010080835404028352916020019161033b565b820191906000526020600020905b81548152906001019060200180831161031e57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103ab9086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156103ef57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610455575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156104dd5773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561049757600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600460209081526040808320338452909152812080548492906104d790849061088c565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260408120805484929061051290849061088c565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120805484929061054c908490610826565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516105b291815260200190565b60405180910390a35060019392505050565b336000908152600360205260409020548111156105e057600080fd5b33600090815260036020526040812080548392906105ff90849061088c565b9091555050604051339082156108fc029083906000818181858888f19350505050158015610631573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600180546102c290610839565b60006106843384846103bd565b9392505050565b61069361025a565b565b600060208083528351808285015260005b818110156106c2578581018301518582016040015282016106a6565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b919050565b6000806040838503121561073d57600080fd5b61074683610701565b946020939093013593505050565b60008060006060848603121561076957600080fd5b61077284610701565b925061078060208501610701565b9150604084013590509250925092565b6000602082840312156107a257600080fd5b5035919050565b6000602082840312156107bb57600080fd5b61068482610701565b600080604083850312156107d757600080fd5b6107e083610701565b91506107ee60208401610701565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103b7576103b76107f7565b600181811c9082168061084d57607f821691505b602082108103610886577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103b7576103b76107f756fea164736f6c6343000813000a",
}
var WETH9ABI = WETH9MetaData.ABI
diff --git a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index 0e49e7b25e7..63299417b22 100644
--- a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -12,3 +12,4 @@ multicall3: ../../../contracts/solc/vendor/Multicall3/Multicall3.sol/Multicall3.
type_and_version: ../../../contracts/solc/shared/ITypeAndVersion/ITypeAndVersion.sol/ITypeAndVersion.abi.json ../../../contracts/solc/shared/ITypeAndVersion/ITypeAndVersion.sol/ITypeAndVersion.bin 21f6da4daa754971a4fdafea90ec64a77a5f03e62f9a9639802726b22eaa380a
vrf_log_emitter: ../../../contracts/solc/shared/VRFLogEmitter/VRFLogEmitter.sol/VRFLogEmitter.abi.json ../../../contracts/solc/shared/VRFLogEmitter/VRFLogEmitter.sol/VRFLogEmitter.bin 46788c9519425dd23befdea8e561ee454dcb559f6a8fe70f4a092805574218f6
werc20_mock: ../../../contracts/solc/shared/WERC20Mock/WERC20Mock.sol/WERC20Mock.abi.json ../../../contracts/solc/shared/WERC20Mock/WERC20Mock.sol/WERC20Mock.bin f5ba13fc99c248354508e3bab6cd0fb66607d3b7377f59a1e80b930e96ed4f48
+weth9: ../../../contracts/solc/vendor/WETH9/WETH9.sol/WETH9.abi.json ../../../contracts/solc/vendor/WETH9/WETH9.sol/WETH9.bin 0a66cf864b2f0853d3d253feec9c65538eaf4419bd2c709d1fad7e546b7a7746
diff --git a/core/gethwrappers/shared/go_generate.go b/core/gethwrappers/shared/go_generate.go
index 30ca631178d..332dd31b662 100644
--- a/core/gethwrappers/shared/go_generate.go
+++ b/core/gethwrappers/shared/go_generate.go
@@ -16,3 +16,4 @@ package gethwrappers
//go:generate go run ../generation/wrap.go vendor ERC20 erc20
//go:generate go run ../generation/wrap.go vendor Multicall3 multicall3
+//go:generate go run ../generation/wrap.go vendor WETH9 weth9
diff --git a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go
index ca75b4a82d9..00bf0f533a7 100644
--- a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go
+++ b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go
@@ -43,7 +43,7 @@ type WorkflowRegistryWorkflowMetadata struct {
var WorkflowRegistryMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddressNotAuthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BinaryURLRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotWorkflowOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"}],\"name\":\"DONNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWorkflowID\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"URLTooLong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyInDesiredStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowContentNotUpdated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowNameRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"WorkflowNameTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AllowedDONsUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AuthorizedAddressesUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"lockedBy\",\"type\":\"address\"}],\"name\":\"RegistryLockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"unlockedBy\",\"type\":\"address\"}],\"name\":\"RegistryUnlockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowActivatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowDeletedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"secretsURLHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowForceUpdateSecretsRequestedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowPausedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowRegisteredV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"oldWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowUpdatedV1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"activateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"computeHashKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"deleteWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedDONs\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"allowedDONs\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"getWorkflowMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByDON\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRegistryLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"pauseWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"registerWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"requestForceUpdateSecrets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAllowedDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAuthorizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"updateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
- Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600b805460ff1916905560405161354290816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a1461213e578063181f5a77146120af5780632303348a14611f725780632b596f6d14611ee45780633ccd14ff14611572578063695e1340146113965780636f351771146112ba578063724c13dd146111af5780637497066b1461109457806379ba509714610fbe5780637ec0846d14610f335780638da5cb5b14610ee15780639f4cb53414610ec0578063b87a019414610e6a578063d4b89c74146106af578063db80009214610614578063e3dce080146104d9578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600b54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760078054610185816124b8565b610192604051918261233f565b81815261019e826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801541661027d82876125ea565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb612426565b6102c3612c83565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576103a760043533612f10565b600181019081549060ff8260c01c1660028110156104805760011461045657780100000000000000000000000000000000000000000000000091817fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff92549060405191602083527f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff8560a01c16938061044d3395600260208401910161268c565b0390a416179055005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e7366123ae565b916104f0612c83565b60ff600b54166104af5782156105ce5760005b82811061059357505b60405191806040840160408552526060830191906000905b80821061055b5785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff821680920361014457600191815260208091019401920190610524565b806105c773ffffffffffffffffffffffffffffffffffffffff6105c16105bc6001958888612b23565b612c62565b166130eb565b5001610503565b60005b8281106105de575061050c565b8061060d73ffffffffffffffffffffffffffffffffffffffff6106076105bc6001958888612b23565b1661331c565b50016105d1565b346101445761063461062536612449565b9161062e6124d0565b50612b44565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff600182015416156106855761066d61068191612740565b6040519182916020835260208301906121fc565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106fe903690600401612380565b9060643567ffffffffffffffff81116101445761071f903690600401612380565b9160843567ffffffffffffffff811161014457610740903690600401612380565b60ff600b94929454166104af57610758818688612d78565b61076460043533612f10565b9163ffffffff600184015460a01c169561077e3388612cce565b8354946107b060405161079f816107988160038b0161268c565b038261233f565b6107aa368c856128f4565b90612f7f565b6107d26040516107c7816107988160048c0161268c565b6107aa3686886128f4565b6107f46040516107e9816107988160058d0161268c565b6107aa36898d6128f4565b918080610e63575b80610e5c575b610e3257610811602435612e68565b88600052600660205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055602435885515610cdd575b15610b8c575b156108df575b926108ca7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad735395936108da936108bc6108ae978d604051998a996024358b5260a060208c0152600260a08c01910161268c565b9189830360408b01526129b7565b9186830360608801526129b7565b90838203608085015233976129b7565b0390a4005b6108ec6005860154612639565b610b25575b67ffffffffffffffff8411610af65761091a846109116005880154612639565b60058801612970565b6000601f85116001146109f6579284926108bc6108ca938a9b9c61099e876108ae9b9a6108da9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f6000926109eb575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c87806109c1575b50509c9b9a995093505092949550925061085c565b6109cb9133612b44565b60005260056020526109e3600435604060002061313d565b508c876109ac565b013590508f8061096c565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610ade5750926108bc6108ca936108da969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108ae9e9d1610610aa6575b505050600187811b0160058a01556109a4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a93565b898c0135825560209b8c019b60019092019101610a06565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b6b81610b3f60058a0133866129f6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261233f565b5190206000526005602052610b8660043560406000206133e3565b506108f1565b67ffffffffffffffff8311610af657610bb583610bac6004890154612639565b60048901612970565b600083601f8111600114610c165780610c0192600091610c0b575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6004870155610856565b90508601358d610bd0565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610cc55750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c8d575b5050600183811b016004870155610856565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c7b565b9091602060018192858a013581550193019101610c27565b67ffffffffffffffff8b11610af657610d068b610cfd60038a0154612639565b60038a01612970565b60008b601f8111600114610d665780610d5192600091610d5b57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610850565b90508501358e610bd0565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610e19578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610de0575b905060018092501b016003880155610850565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610dcd565b5085820135835560019092019160209182019101610d77565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b5082610802565b50816107fc565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610681610eb4610ea7612426565b6044359060243590612b9f565b604051918291826122a0565b34610144576020610ed9610ed336612449565b91612b44565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f6a612c83565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b5416600b557f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a6020604051338152a1005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361106a57600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600980546110d0816124b8565b6110dd604051918261233f565b8181526110e9826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061116d57505050906040519283926020840190602085525180915260408401929160005b82811061115057505050500390f35b835163ffffffff1685528695509381019392810192600101611141565b6001908260005263ffffffff817f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0154166111a882876125ea565b520161111a565b34610144576111bd366123ae565b916111c6612c83565b60ff600b54166104af5782156112845760005b82811061125957505b60405191806040840160408552526060830191906000905b8082106112315785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff8216809203610144576001918152602080910194019201906111fa565b8061127d63ffffffff6112776112726001958888612b23565b612b33565b16613032565b50016111d9565b60005b82811061129457506111e2565b806112b363ffffffff6112ad6112726001958888612b23565b166131c9565b5001611287565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576112ff60043533612f10565b6001810190815463ffffffff8160a01c1660ff8260c01c1660028110156104805715610456577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff926113513383612cce565b80547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061138e3395600260208401910161268c565b0390a4169055005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600b54166104af576113de8233612f10565b916113f6336000526008602052604060002054151590565b156115425782600493546000526006835260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905533600052600283526114488260406000206133e3565b50600181019063ffffffff80835460a01c166000526003855261146f8460406000206133e3565b506005820161147e8154612639565b61150e575b508154925460a01c16917f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de19141322571604051868152806114c6339560028a8401910161268c565b0390a46000525261150c6005604060002060008155600060018201556114ee60028201612ada565b6114fa60038201612ada565b61150660048201612ada565b01612ada565b005b60405161152381610b3f8982019433866129f6565b5190206000526005855261153b8460406000206133e3565b5086611483565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115c1903690600401612380565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff8111610144576115fd903690600401612380565b91909260a43567ffffffffffffffff811161014457611620903690600401612380565b60c43567ffffffffffffffff811161014457611640903690600401612380565b96909560ff600b54166104af57611657338a612cce565b8415611eba5760408511611e8257611670888483612d78565b61167b858733612b44565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611e58576116b2602435612e68565b604051906116bf82612322565b602435825233602083015263ffffffff8b1660408301526116e56064356060840161262d565b6116f036888a6128f4565b60808301526117003684866128f4565b60a08301526117103686886128f4565b60c0830152611720368b8b6128f4565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b1690606085015160028110156104805778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610af657611803826117fa6002880154612639565b60028801612970565b602090601f8311600114611d8c57611850929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610af6576118878261187e6003880154612639565b60038801612970565b602090601f8311600114611cc0576118d4929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610af65761190b826119026004880154612639565b60048801612970565b602090601f8311600114611be857918061195c9260e09594600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610af657838d926119948e9661198b6005860154612639565b60058601612970565b602090601f8311600114611ace579463ffffffff6108bc95819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d9994611a20876108da9f9b98600593611a849f9a600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b336000526002602052611a3b83604060002061313d565b50166000526003602052611a5381604060002061313d565b508d82611a9a575b5050506108ae6040519a8b9a611a738c606435612191565b60a060208d015260a08c01916129b7565b97838903608085015216963396602435966129b7565b611aba92611aa89133612b44565b6000526005602052604060002061313d565b508c8f8d611a5b565b01519050388061096c565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611bbe57506108bc9563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d99946001876108da9f9b96928f9693611a849f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611b87575b505050811b01910155611a24565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611b79565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611adf565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c9d5750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611c66575b505050811b016004850155611962565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611c56565b91926020600181928685015181550194019201611bf9565b015190508f8061096c565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611d715760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d3a575b505050811b0160038401556118da565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d2a565b81810151835560209485019460019093019290910190611cd3565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611e3d5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611e06575b505050811b016002840155611856565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611df6565b81810151835560209485019460019093019290910190611d9f565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b60046040517f485b8ed4000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611f1b612c83565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b541617600b557f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c6020604051338152a1005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611fc2903690600401612380565b60ff600b54166104af57611fd69133612b44565b9081600052600560205260406000209182549182156106855760005b838110611ffb57005b806120086001928761301a565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c16600052600a8452604060002054151580612092575b612049575b5001611ff2565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb673604051868152604086820152806120893394600260408401910161268c565b0390a286612042565b506120aa336000526008602052604060002054151590565b61203d565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610af65761068191604052601a81527f576f726b666c6f77526567697374727920312e302e302d646576000000000000602082015260405191829160208352602083019061219e565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610eb46106819160443590602435906127ff565b9060028210156104805752565b919082519283825260005b8481106121e85750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016121a9565b61229d9160e061228c61227a6122686101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff604088015116604087015261225460608801516060880190612191565b60808701519080608088015286019061219e565b60a086015185820360a087015261219e565b60c085015184820360c086015261219e565b9201519060e081840391015261219e565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106122d65750505050505090565b9091929394958480612312837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516121fc565b98019301930191949392906122c6565b610100810190811067ffffffffffffffff821117610af657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610af657604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff8211610144576124b491600401612380565b9091565b67ffffffffffffffff8111610af65760051b60200190565b604051906124dd82612322565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610af6576040526000815290565b9061253e826124b8565b61254b604051918261233f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061257982946124b8565b019060005b82811061258a57505050565b6020906125956124d0565b8282850101520161257e565b919082018092116125ae57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116125ae57565b80518210156125fe5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60028210156104805752565b90600182811c92168015612682575b602083101461265357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612648565b80546000939261269b82612639565b9182825260209360019160018116908160001461270357506001146126c2575b5050505050565b90939495506000929192528360002092846000945b8386106126ef575050505001019038808080806126bb565b8054858701830152940193859082016126d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b0101915038808080806126bb565b90600560e06040936127fb85519161275783612322565b6127f48397825485526127a160ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c166060870161262d565b80516127b481610798816002880161268c565b608086015280516127cc81610798816003880161268c565b60a086015280516127e481610798816004880161268c565b60c086015251809681930161268c565b038461233f565b0152565b63ffffffff1691600083815260036020906003602052604093604084205490818710156128e4576128539181606489931180156128dc575b6128d4575b8161284782856125a1565b11156128c457506125dd565b9461285d86612534565b96845b87811061287257505050505050505090565b60019082875284865261289188882061288b83876125a1565b9061301a565b905490861b1c8752600486526128a8888820612740565b6128b2828c6125ea565b526128bd818b6125ea565b5001612860565b6128cf9150826125a1565b6125dd565b50606461283c565b508015612837565b505050505050505061229d612510565b92919267ffffffffffffffff8211610af6576040519161293c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461233f565b829481845281830111610144578281602093846000960137010152565b818110612964575050565b60008155600101612959565b9190601f811161297f57505050565b6129ab926000526020600020906020601f840160051c830193106129ad575b601f0160051c0190612959565b565b909150819061299e565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b168252601490600092815492612a3284612639565b92600194600181169081600014612a995750600114612a54575b505050505090565b9091929395945060005260209460206000206000905b858210612a865750505050601492935001013880808080612a4c565b8054858301850152908701908201612a6a565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612a4c565b612ae48154612639565b9081612aee575050565b81601f60009311600114612b00575055565b908083918252612b1f601f60208420940160051c840160018501612959565b5555565b91908110156125fe5760051b0190565b3563ffffffff811681036101445790565b91906034612b9991836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b16885284840137810160008382015203601481018452018261233f565b51902090565b73ffffffffffffffffffffffffffffffffffffffff169160008381526002926020906002602052604093604084205490818310156128e457612bf69181606485931180156128dc576128d4578161284782856125a1565b94612c0086612534565b96845b878110612c1557505050505050505090565b600190828752838652612c2e88882061288b83886125a1565b90549060031b1c875260048652612c46888820612740565b612c50828c6125ea565b52612c5b818b6125ea565b5001612c03565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612ca457565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600a60205260406000205415612d47575073ffffffffffffffffffffffffffffffffffffffff1680600052600860205260406000205415612d165750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b908115612e3e5760c891828111612e085750818111612dd35750808211612d9d575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f9cd963cf000000000000000000000000000000000000000000000000000000008152fd5b8015612ee65780600052600660205260ff60406000205416612ebc576000526006602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b60046040517f4cb050e4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff806001840154169182156106855716809103612f4e575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612f96575b5050505090565b6020929394508201209201201438808080612f8f565b6009548110156125fe5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b6007548110156125fe5760076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880190600090565b80548210156125fe5760005260206000200190600090565b6000818152600a60205260408120546130e657600954680100000000000000008110156130b95790826130a561307084600160409601600955612fac565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600954928152600a6020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b6000818152600860205260408120546130e657600754680100000000000000008110156130b957908261312961307084600160409601600755612fe3565b905560075492815260086020522055600190565b919060018301600090828252806020526040822054156000146131c357845494680100000000000000008610156131965783613186613070886001604098999a0185558461301a565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b6000818152600a60205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600954908382019182116132bd57818103613289575b505050600954801561325c5781019061323b82612fac565b909182549160031b1b191690556009558152600a6020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6132a761329861307093612fac565b90549060031b1c928392612fac565b90558452600a6020526040842055388080613223565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b6000818152600860205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600754908382019182116132bd578181036133af575b505050600754801561325c5781019061338e82612fe3565b909182549160031b1b19169055600755815260086020526040812055600190565b6133cd6133be61307093612fe3565b90549060031b1c928392612fe3565b9055845260086020526040842055388080613376565b90600182019060009281845282602052604084205490811515600014612f8f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91828101818111613508578254908482019182116134db578181036134a6575b505050805480156134795782019161345c838361301a565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6134c66134b6613070938661301a565b90549060031b1c9283928661301a565b90558652846020526040862055388080613444565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a",
+ Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600b805460ff1916905560405161354290816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a1461213e578063181f5a77146120af5780632303348a14611f725780632b596f6d14611ee45780633ccd14ff14611572578063695e1340146113965780636f351771146112ba578063724c13dd146111af5780637497066b1461109457806379ba509714610fbe5780637ec0846d14610f335780638da5cb5b14610ee15780639f4cb53414610ec0578063b87a019414610e6a578063d4b89c74146106af578063db80009214610614578063e3dce080146104d9578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600b54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760078054610185816124b8565b610192604051918261233f565b81815261019e826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801541661027d82876125ea565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb612426565b6102c3612c83565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576103a760043533612f10565b600181019081549060ff8260c01c1660028110156104805760011461045657780100000000000000000000000000000000000000000000000091817fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff92549060405191602083527f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff8560a01c16938061044d3395600260208401910161268c565b0390a416179055005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e7366123ae565b916104f0612c83565b60ff600b54166104af5782156105ce5760005b82811061059357505b60405191806040840160408552526060830191906000905b80821061055b5785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff821680920361014457600191815260208091019401920190610524565b806105c773ffffffffffffffffffffffffffffffffffffffff6105c16105bc6001958888612b23565b612c62565b166130eb565b5001610503565b60005b8281106105de575061050c565b8061060d73ffffffffffffffffffffffffffffffffffffffff6106076105bc6001958888612b23565b1661331c565b50016105d1565b346101445761063461062536612449565b9161062e6124d0565b50612b44565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff600182015416156106855761066d61068191612740565b6040519182916020835260208301906121fc565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106fe903690600401612380565b9060643567ffffffffffffffff81116101445761071f903690600401612380565b9160843567ffffffffffffffff811161014457610740903690600401612380565b60ff600b94929454166104af57610758818688612d78565b61076460043533612f10565b9163ffffffff600184015460a01c169561077e3388612cce565b8354946107b060405161079f816107988160038b0161268c565b038261233f565b6107aa368c856128f4565b90612f7f565b6107d26040516107c7816107988160048c0161268c565b6107aa3686886128f4565b6107f46040516107e9816107988160058d0161268c565b6107aa36898d6128f4565b918080610e63575b80610e5c575b610e3257610811602435612e68565b88600052600660205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055602435885515610cdd575b15610b8c575b156108df575b926108ca7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad735395936108da936108bc6108ae978d604051998a996024358b5260a060208c0152600260a08c01910161268c565b9189830360408b01526129b7565b9186830360608801526129b7565b90838203608085015233976129b7565b0390a4005b6108ec6005860154612639565b610b25575b67ffffffffffffffff8411610af65761091a846109116005880154612639565b60058801612970565b6000601f85116001146109f6579284926108bc6108ca938a9b9c61099e876108ae9b9a6108da9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f6000926109eb575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c87806109c1575b50509c9b9a995093505092949550925061085c565b6109cb9133612b44565b60005260056020526109e3600435604060002061313d565b508c876109ac565b013590508f8061096c565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610ade5750926108bc6108ca936108da969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108ae9e9d1610610aa6575b505050600187811b0160058a01556109a4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a93565b898c0135825560209b8c019b60019092019101610a06565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b6b81610b3f60058a0133866129f6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261233f565b5190206000526005602052610b8660043560406000206133e3565b506108f1565b67ffffffffffffffff8311610af657610bb583610bac6004890154612639565b60048901612970565b600083601f8111600114610c165780610c0192600091610c0b575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6004870155610856565b90508601358d610bd0565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610cc55750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c8d575b5050600183811b016004870155610856565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c7b565b9091602060018192858a013581550193019101610c27565b67ffffffffffffffff8b11610af657610d068b610cfd60038a0154612639565b60038a01612970565b60008b601f8111600114610d665780610d5192600091610d5b57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610850565b90508501358e610bd0565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610e19578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610de0575b905060018092501b016003880155610850565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610dcd565b5085820135835560019092019160209182019101610d77565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b5082610802565b50816107fc565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610681610eb4610ea7612426565b6044359060243590612b9f565b604051918291826122a0565b34610144576020610ed9610ed336612449565b91612b44565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f6a612c83565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b5416600b557f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a6020604051338152a1005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361106a57600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600980546110d0816124b8565b6110dd604051918261233f565b8181526110e9826124b8565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061116d57505050906040519283926020840190602085525180915260408401929160005b82811061115057505050500390f35b835163ffffffff1685528695509381019392810192600101611141565b6001908260005263ffffffff817f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0154166111a882876125ea565b520161111a565b34610144576111bd366123ae565b916111c6612c83565b60ff600b54166104af5782156112845760005b82811061125957505b60405191806040840160408552526060830191906000905b8082106112315785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff8216809203610144576001918152602080910194019201906111fa565b8061127d63ffffffff6112776112726001958888612b23565b612b33565b16613032565b50016111d9565b60005b82811061129457506111e2565b806112b363ffffffff6112ad6112726001958888612b23565b166131c9565b5001611287565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104af576112ff60043533612f10565b6001810190815463ffffffff8160a01c1660ff8260c01c1660028110156104805715610456577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff926113513383612cce565b80547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061138e3395600260208401910161268c565b0390a4169055005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600b54166104af576113de8233612f10565b916113f6336000526008602052604060002054151590565b156115425782600493546000526006835260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815416905533600052600283526114488260406000206133e3565b50600181019063ffffffff80835460a01c166000526003855261146f8460406000206133e3565b506005820161147e8154612639565b61150e575b508154925460a01c16917f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de19141322571604051868152806114c6339560028a8401910161268c565b0390a46000525261150c6005604060002060008155600060018201556114ee60028201612ada565b6114fa60038201612ada565b61150660048201612ada565b01612ada565b005b60405161152381610b3f8982019433866129f6565b5190206000526005855261153b8460406000206133e3565b5086611483565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115c1903690600401612380565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff8111610144576115fd903690600401612380565b91909260a43567ffffffffffffffff811161014457611620903690600401612380565b60c43567ffffffffffffffff811161014457611640903690600401612380565b96909560ff600b54166104af57611657338a612cce565b8415611eba5760408511611e8257611670888483612d78565b61167b858733612b44565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611e58576116b2602435612e68565b604051906116bf82612322565b602435825233602083015263ffffffff8b1660408301526116e56064356060840161262d565b6116f036888a6128f4565b60808301526117003684866128f4565b60a08301526117103686886128f4565b60c0830152611720368b8b6128f4565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b1690606085015160028110156104805778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610af657611803826117fa6002880154612639565b60028801612970565b602090601f8311600114611d8c57611850929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610af6576118878261187e6003880154612639565b60038801612970565b602090601f8311600114611cc0576118d4929160009183611cb55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610af65761190b826119026004880154612639565b60048801612970565b602090601f8311600114611be857918061195c9260e09594600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610af657838d926119948e9661198b6005860154612639565b60058601612970565b602090601f8311600114611ace579463ffffffff6108bc95819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d9994611a20876108da9f9b98600593611a849f9a600092611ac35750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b336000526002602052611a3b83604060002061313d565b50166000526003602052611a5381604060002061313d565b508d82611a9a575b5050506108ae6040519a8b9a611a738c606435612191565b60a060208d015260a08c01916129b7565b97838903608085015216963396602435966129b7565b611aba92611aa89133612b44565b6000526005602052604060002061313d565b508c8f8d611a5b565b01519050388061096c565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611bbe57506108bc9563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d99946001876108da9f9b96928f9693611a849f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611b87575b505050811b01910155611a24565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611b79565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611adf565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c9d5750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611c66575b505050811b016004850155611962565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611c56565b91926020600181928685015181550194019201611bf9565b015190508f8061096c565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611d715760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d3a575b505050811b0160038401556118da565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d2a565b81810151835560209485019460019093019290910190611cd3565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611e3d5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611e06575b505050811b016002840155611856565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611df6565b81810151835560209485019460019093019290910190611d9f565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b60046040517f485b8ed4000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611f1b612c83565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b541617600b557f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c6020604051338152a1005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611fc2903690600401612380565b60ff600b54166104af57611fd69133612b44565b9081600052600560205260406000209182549182156106855760005b838110611ffb57005b806120086001928761301a565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c16600052600a8452604060002054151580612092575b612049575b5001611ff2565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb673604051868152604086820152806120893394600260408401910161268c565b0390a286612042565b506120aa336000526008602052604060002054151590565b61203d565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610af65761068191604052601681527f576f726b666c6f77526567697374727920312e302e3000000000000000000000602082015260405191829160208352602083019061219e565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610eb46106819160443590602435906127ff565b9060028210156104805752565b919082519283825260005b8481106121e85750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016121a9565b61229d9160e061228c61227a6122686101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff604088015116604087015261225460608801516060880190612191565b60808701519080608088015286019061219e565b60a086015185820360a087015261219e565b60c085015184820360c086015261219e565b9201519060e081840391015261219e565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106122d65750505050505090565b9091929394958480612312837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516121fc565b98019301930191949392906122c6565b610100810190811067ffffffffffffffff821117610af657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610af657604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff8211610144576124b491600401612380565b9091565b67ffffffffffffffff8111610af65760051b60200190565b604051906124dd82612322565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610af6576040526000815290565b9061253e826124b8565b61254b604051918261233f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061257982946124b8565b019060005b82811061258a57505050565b6020906125956124d0565b8282850101520161257e565b919082018092116125ae57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116125ae57565b80518210156125fe5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60028210156104805752565b90600182811c92168015612682575b602083101461265357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612648565b80546000939261269b82612639565b9182825260209360019160018116908160001461270357506001146126c2575b5050505050565b90939495506000929192528360002092846000945b8386106126ef575050505001019038808080806126bb565b8054858701830152940193859082016126d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b0101915038808080806126bb565b90600560e06040936127fb85519161275783612322565b6127f48397825485526127a160ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c166060870161262d565b80516127b481610798816002880161268c565b608086015280516127cc81610798816003880161268c565b60a086015280516127e481610798816004880161268c565b60c086015251809681930161268c565b038461233f565b0152565b63ffffffff1691600083815260036020906003602052604093604084205490818710156128e4576128539181606489931180156128dc575b6128d4575b8161284782856125a1565b11156128c457506125dd565b9461285d86612534565b96845b87811061287257505050505050505090565b60019082875284865261289188882061288b83876125a1565b9061301a565b905490861b1c8752600486526128a8888820612740565b6128b2828c6125ea565b526128bd818b6125ea565b5001612860565b6128cf9150826125a1565b6125dd565b50606461283c565b508015612837565b505050505050505061229d612510565b92919267ffffffffffffffff8211610af6576040519161293c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461233f565b829481845281830111610144578281602093846000960137010152565b818110612964575050565b60008155600101612959565b9190601f811161297f57505050565b6129ab926000526020600020906020601f840160051c830193106129ad575b601f0160051c0190612959565b565b909150819061299e565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b168252601490600092815492612a3284612639565b92600194600181169081600014612a995750600114612a54575b505050505090565b9091929395945060005260209460206000206000905b858210612a865750505050601492935001013880808080612a4c565b8054858301850152908701908201612a6a565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612a4c565b612ae48154612639565b9081612aee575050565b81601f60009311600114612b00575055565b908083918252612b1f601f60208420940160051c840160018501612959565b5555565b91908110156125fe5760051b0190565b3563ffffffff811681036101445790565b91906034612b9991836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b16885284840137810160008382015203601481018452018261233f565b51902090565b73ffffffffffffffffffffffffffffffffffffffff169160008381526002926020906002602052604093604084205490818310156128e457612bf69181606485931180156128dc576128d4578161284782856125a1565b94612c0086612534565b96845b878110612c1557505050505050505090565b600190828752838652612c2e88882061288b83886125a1565b90549060031b1c875260048652612c46888820612740565b612c50828c6125ea565b52612c5b818b6125ea565b5001612c03565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612ca457565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600a60205260406000205415612d47575073ffffffffffffffffffffffffffffffffffffffff1680600052600860205260406000205415612d165750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b908115612e3e5760c891828111612e085750818111612dd35750808211612d9d575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f9cd963cf000000000000000000000000000000000000000000000000000000008152fd5b8015612ee65780600052600660205260ff60406000205416612ebc576000526006602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b60046040517f4cb050e4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff806001840154169182156106855716809103612f4e575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612f96575b5050505090565b6020929394508201209201201438808080612f8f565b6009548110156125fe5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b6007548110156125fe5760076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880190600090565b80548210156125fe5760005260206000200190600090565b6000818152600a60205260408120546130e657600954680100000000000000008110156130b95790826130a561307084600160409601600955612fac565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600954928152600a6020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b6000818152600860205260408120546130e657600754680100000000000000008110156130b957908261312961307084600160409601600755612fe3565b905560075492815260086020522055600190565b919060018301600090828252806020526040822054156000146131c357845494680100000000000000008610156131965783613186613070886001604098999a0185558461301a565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b6000818152600a60205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600954908382019182116132bd57818103613289575b505050600954801561325c5781019061323b82612fac565b909182549160031b1b191690556009558152600a6020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6132a761329861307093612fac565b90549060031b1c928392612fac565b90558452600a6020526040842055388080613223565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b6000818152600860205260408120549091908015613317577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff908181018181116132ea57600754908382019182116132bd578181036133af575b505050600754801561325c5781019061338e82612fe3565b909182549160031b1b19169055600755815260086020526040812055600190565b6133cd6133be61307093612fe3565b90549060031b1c928392612fe3565b9055845260086020526040842055388080613376565b90600182019060009281845282602052604084205490811515600014612f8f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91828101818111613508578254908482019182116134db578181036134a6575b505050805480156134795782019161345c838361301a565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6134c66134b6613070938661301a565b90549060031b1c9283928661301a565b90558652846020526040862055388080613444565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a",
}
var WorkflowRegistryABI = WorkflowRegistryMetaData.ABI
diff --git a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt
index afc0ccbefd9..25a00593acb 100644
--- a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt
+++ b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt
@@ -1,2 +1,2 @@
GETH_VERSION: 1.14.11
-workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin 88356c4673d32f7d17b5e418d411a418a24ac972e6ec9cb740d8b731d6b9916a
+workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin 6384706f1c2cecc49b8f42dbb9a1bed450c3a7ae576aaaa3c50237b52c7e676e
diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go
index db4da59dcfb..ae3b8c5e243 100644
--- a/core/internal/cltest/cltest.go
+++ b/core/internal/cltest/cltest.go
@@ -37,6 +37,9 @@ import (
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types"
+ "github.com/smartcontractkit/chainlink/v2/core/capabilities/compute"
+ "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer"
+
"github.com/smartcontractkit/chainlink-common/pkg/loop"
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
"github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
@@ -276,7 +279,6 @@ func NewApplicationWithConfigAndKey(t testing.TB, c chainlink.GeneralConfig, fla
func setKeys(t testing.TB, app *TestApplication, flagsAndDeps ...interface{}) (chainID ubig.Big) {
ctx := testutils.Context(t)
- require.NoError(t, app.KeyStore.Unlock(ctx, Password))
for _, dep := range flagsAndDeps {
switch v := dep.(type) {
@@ -357,6 +359,22 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
}
}
+ var syncerFetcherFunc syncer.FetcherFunc
+ for _, dep := range flagsAndDeps {
+ syncerFetcherFunc, _ = dep.(syncer.FetcherFunc)
+ if syncerFetcherFunc != nil {
+ break
+ }
+ }
+
+ var computeFetcherFactory compute.FetcherFactory
+ for _, dep := range flagsAndDeps {
+ computeFetcherFactory, _ = dep.(compute.FetcherFactory)
+ if computeFetcherFactory != nil {
+ break
+ }
+ }
+
var peerWrapper p2ptypes.PeerWrapper
for _, dep := range flagsAndDeps {
peerWrapper, _ = dep.(p2ptypes.PeerWrapper)
@@ -392,6 +410,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
}
keyStore := keystore.NewInMemory(ds, utils.FastScryptParams, lggr)
+ require.NoError(t, keyStore.Unlock(ctx, Password))
mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox"))
loopRegistry := plugins.NewTestLoopRegistry(lggr)
@@ -417,7 +436,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
evmOpts := chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
@@ -505,6 +524,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn
CapabilitiesDispatcher: dispatcher,
CapabilitiesPeerWrapper: peerWrapper,
NewOracleFactoryFn: newOracleFactoryFn,
+ FetcherFunc: syncerFetcherFunc,
+ FetcherFactoryFn: computeFetcherFactory,
RetirementReportCache: retirementReportCache,
})
diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go
index b2ad81bb2c2..24922715eda 100644
--- a/core/internal/cltest/mocks.go
+++ b/core/internal/cltest/mocks.go
@@ -28,6 +28,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/sessions"
"github.com/smartcontractkit/chainlink/v2/core/web"
evmclient "github.com/smartcontractkit/chainlink/v2/evm/client"
+ "github.com/smartcontractkit/chainlink/v2/evm/config/toml"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
)
@@ -398,7 +399,7 @@ func (m MockPasswordPrompter) Prompt() string {
return m.Password
}
-func NewLegacyChainsWithMockChain(t testing.TB, ethClient evmclient.Client, cfg legacyevm.AppConfig) legacyevm.LegacyChainContainer {
+func NewLegacyChainsWithMockChain(t testing.TB, ethClient evmclient.Client, cfg toml.HasEVMConfigs) legacyevm.LegacyChainContainer {
ch := new(evmmocks.Chain)
ch.On("Client").Return(ethClient)
ch.On("Logger").Return(logger.TestLogger(t))
@@ -410,7 +411,7 @@ func NewLegacyChainsWithMockChain(t testing.TB, ethClient evmclient.Client, cfg
return NewLegacyChainsWithChain(ch, cfg)
}
-func NewLegacyChainsWithMockChainAndTxManager(t testing.TB, ethClient evmclient.Client, cfg legacyevm.AppConfig, txm txmgr.TxManager) legacyevm.LegacyChainContainer {
+func NewLegacyChainsWithMockChainAndTxManager(t testing.TB, ethClient evmclient.Client, cfg toml.HasEVMConfigs, txm txmgr.TxManager) legacyevm.LegacyChainContainer {
ch := new(evmmocks.Chain)
ch.On("Client").Return(ethClient)
ch.On("Logger").Return(logger.TestLogger(t))
@@ -422,7 +423,7 @@ func NewLegacyChainsWithMockChainAndTxManager(t testing.TB, ethClient evmclient.
return NewLegacyChainsWithChain(ch, cfg)
}
-func NewLegacyChainsWithChain(ch legacyevm.Chain, cfg legacyevm.AppConfig) legacyevm.LegacyChainContainer {
+func NewLegacyChainsWithChain(ch legacyevm.Chain, cfg toml.HasEVMConfigs) legacyevm.LegacyChainContainer {
m := map[string]legacyevm.Chain{ch.ID().String(): ch}
return legacyevm.NewLegacyChains(m, cfg.EVMConfigs())
}
diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go
index c69ce1defc5..929a9b22aaf 100644
--- a/core/internal/features/features_test.go
+++ b/core/internal/features/features_test.go
@@ -1286,7 +1286,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) {
require.NoError(t, kst.Unlock(ctx, cltest.Password))
chainsAndConfig := evmtest.NewLegacyChainsAndConfig(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go
index 685736827db..6bfab4166c5 100644
--- a/core/internal/testutils/evmtest/evmtest.go
+++ b/core/internal/testutils/evmtest/evmtest.go
@@ -36,7 +36,7 @@ import (
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
-func NewChainScopedConfig(t testing.TB, cfg legacyevm.AppConfig) evmconfig.ChainScopedConfig {
+func NewChainScopedConfig(t testing.TB, cfg configtoml.HasEVMConfigs) evmconfig.ChainScopedConfig {
var evmCfg *configtoml.EVMConfig
if len(cfg.EVMConfigs()) > 0 {
evmCfg = cfg.EVMConfigs()[0]
@@ -48,14 +48,14 @@ func NewChainScopedConfig(t testing.TB, cfg legacyevm.AppConfig) evmconfig.Chain
}
}
- return evmconfig.NewTOMLChainScopedConfig(evmCfg, logger.TestLogger(t))
+ return evmconfig.NewTOMLChainScopedConfig(evmCfg)
}
type TestChainOpts struct {
Client evmclient.Client
LogBroadcaster log.Broadcaster
LogPoller logpoller.LogPoller
- GeneralConfig legacyevm.AppConfig
+ ChainConfigs configtoml.EVMConfigs
DatabaseConfig txmgr.DatabaseConfig
FeatureConfig legacyevm.FeatureConfig
ListenerConfig txmgr.ListenerConfig
@@ -90,7 +90,7 @@ func NewChainOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainRelayOpts
Logger: lggr,
KeyStore: testopts.KeyStore,
ChainOpts: legacyevm.ChainOpts{
- AppConfig: testopts.GeneralConfig,
+ ChainConfigs: testopts.ChainConfigs,
DatabaseConfig: testopts.DatabaseConfig,
ListenerConfig: testopts.ListenerConfig,
FeatureConfig: testopts.FeatureConfig,
@@ -103,7 +103,7 @@ func NewChainOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainRelayOpts
if testopts.Client != nil {
return testopts.Client
}
- return evmclient.NewNullClient(MustGetDefaultChainID(t, testopts.GeneralConfig.EVMConfigs()), logger.TestLogger(t))
+ return evmclient.NewNullClient(MustGetDefaultChainID(t, testopts.ChainConfigs), logger.TestLogger(t))
}
if testopts.LogBroadcaster != nil {
opts.GenLogBroadcaster = func(*big.Int) log.Broadcaster {
@@ -301,10 +301,12 @@ func nodeStatus(n *configtoml.Node, chainID string) (types.NodeStatus, error) {
return s, nil
}
+// Deprecated: use clienttest.NewClient
func NewEthClientMock(t *testing.T) *clienttest.Client {
return clienttest.NewClient(t)
}
+// Deprecated: use clienttest.NewClientWithDefaultChainID
func NewEthClientMockWithDefaultChain(t *testing.T) *clienttest.Client {
c := NewEthClientMock(t)
c.On("ConfiguredChainID").Return(testutils.FixtureChainID).Maybe()
diff --git a/core/internal/testutils/evmtest/v2/evmtest.go b/core/internal/testutils/evmtest/v2/evmtest.go
index 53666768442..5f8d93f851c 100644
--- a/core/internal/testutils/evmtest/v2/evmtest.go
+++ b/core/internal/testutils/evmtest/v2/evmtest.go
@@ -3,7 +3,6 @@ package v2
import (
"testing"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/evm/config"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/utils/big"
@@ -17,5 +16,5 @@ func ChainArbitrumRinkeby(t *testing.T) config.ChainScopedConfig { return scoped
func scopedConfig(t *testing.T, chainID int64) config.ChainScopedConfig {
id := big.NewI(chainID)
evmCfg := toml.EVMConfig{ChainID: id, Chain: toml.Defaults(id)}
- return config.NewTOMLChainScopedConfig(&evmCfg, logger.TestLogger(t))
+ return config.NewTOMLChainScopedConfig(&evmCfg)
}
diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go
index c2f7351186e..f1d92e2a734 100644
--- a/core/internal/testutils/testutils.go
+++ b/core/internal/testutils/testutils.go
@@ -5,7 +5,6 @@ import (
"crypto/ecdsa"
"crypto/rand"
"encoding/base64"
- "flag"
"fmt"
"math"
"math/big"
@@ -50,6 +49,7 @@ var SimulatedChainID = big.NewInt(1337)
// MustNewSimTransactor returns a transactor for interacting with the
// geth simulated backend.
+// TODO use evm/testutils
func MustNewSimTransactor(t testing.TB) *bind.TransactOpts {
key, err := crypto.GenerateKey()
require.NoError(t, err)
@@ -418,10 +418,6 @@ func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected
require.Equal(t, expected, count)
}
-func NewTestFlagSet() *flag.FlagSet {
- return flag.NewFlagSet("test", flag.PanicOnError)
-}
-
// Ptr takes pointer of anything
func Ptr[T any](v T) *T {
return &v
diff --git a/core/scripts/ccip/manual-execution/go.mod b/core/scripts/ccip/manual-execution/go.mod
index 91e028c9314..ed13b108889 100644
--- a/core/scripts/ccip/manual-execution/go.mod
+++ b/core/scripts/ccip/manual-execution/go.mod
@@ -5,7 +5,7 @@ go 1.20
require (
github.com/ethereum/go-ethereum v1.11.3
github.com/pkg/errors v0.9.1
- github.com/smartcontractkit/chain-selectors v1.0.35
+ github.com/smartcontractkit/chain-selectors v1.0.37
go.uber.org/multierr v1.1.0
golang.org/x/crypto v0.1.0
)
diff --git a/core/scripts/ccip/manual-execution/go.sum b/core/scripts/ccip/manual-execution/go.sum
index 3d4ea701977..d03d309b2a8 100644
--- a/core/scripts/ccip/manual-execution/go.sum
+++ b/core/scripts/ccip/manual-execution/go.sum
@@ -72,8 +72,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
-github.com/smartcontractkit/chain-selectors v1.0.35 h1:k7iJqChFbH10WFpahjDtDJoYyDz4qRNq6ReIB41M8Tg=
-github.com/smartcontractkit/chain-selectors v1.0.35/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go
index 8bbb4a566c9..5bfac87a08d 100644
--- a/core/scripts/chaincli/handler/debug.go
+++ b/core/scripts/chaincli/handler/debug.go
@@ -20,7 +20,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
- types2 "github.com/smartcontractkit/chainlink-common/pkg/types"
+ commontypes "github.com/smartcontractkit/chainlink-common/pkg/types"
ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation"
commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex"
@@ -270,7 +270,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) {
// handle data streams lookup
if checkResult.UpkeepFailureReason == uint8(encoding.UpkeepFailureReasonTargetCheckReverted) {
- mc := &types2.MercuryCredentials{LegacyURL: k.cfg.DataStreamsLegacyURL, URL: k.cfg.DataStreamsURL, Username: k.cfg.DataStreamsID, Password: k.cfg.DataStreamsKey}
+ mc := &commontypes.MercuryCredentials{LegacyURL: k.cfg.DataStreamsLegacyURL, URL: k.cfg.DataStreamsURL, Username: k.cfg.DataStreamsID, Password: k.cfg.DataStreamsKey}
mercuryConfig := evm21.NewMercuryConfig(mc, core.StreamsCompatibleABI)
lggr, _ := logger.NewLogger()
blockSub := &blockSubscriber{k.client}
@@ -564,7 +564,7 @@ func mustUpkeepWorkID(upkeepID *big.Int, trigger ocr2keepers.Trigger) [32]byte {
}
var result [32]byte
- copy(result[:], workIDBytes[:])
+ copy(result[:], workIDBytes)
return result
}
diff --git a/core/scripts/common/avalanche.go b/core/scripts/common/avalanche.go
index 8699463c365..b0d94e52429 100644
--- a/core/scripts/common/avalanche.go
+++ b/core/scripts/common/avalanche.go
@@ -79,7 +79,7 @@ func (b *AvaBloom) UnmarshalText(input []byte) error {
// bloomValues returns the bytes (index-value pairs) to set for the given data
func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) {
sha := crypto.NewKeccakState()
- sha.Write(data) //nolint:errcheck
+ sha.Write(data)
sha.Read(hashbuf) //nolint:errcheck
// The actual bits to flip
v1 := byte(1 << (hashbuf[1] & 0x7))
diff --git a/core/scripts/common/helpers.go b/core/scripts/common/helpers.go
index f852c88de5b..fed8249e550 100644
--- a/core/scripts/common/helpers.go
+++ b/core/scripts/common/helpers.go
@@ -506,7 +506,7 @@ func GetRlpHeaders(env Environment, blockNumbers []*big.Int, getParentBlocks boo
// Sanity check - can be un-commented if storeVerifyHeader is failing due to unexpected
// blockhash.
- //bh := crypto.Keccak256Hash(rlpHeader)
+ // bh := crypto.Keccak256Hash(rlpHeader)
//fmt.Println("Calculated BH:", bh.String(),
// "fetched BH:", h.Hash(),
// "block number:", new(big.Int).Set(blockNum).Add(blockNum, offset).String())
diff --git a/core/scripts/common/vrf/constants/constants.go b/core/scripts/common/vrf/constants/constants.go
index 2a064593986..350a7ef8a24 100644
--- a/core/scripts/common/vrf/constants/constants.go
+++ b/core/scripts/common/vrf/constants/constants.go
@@ -17,7 +17,7 @@ var (
StalenessSeconds = int64(86400)
GasAfterPayment = int64(33285)
- //vrfv2
+ // vrfv2
FlatFeeTier1 = int64(500)
FlatFeeTier2 = int64(500)
FlatFeeTier3 = int64(500)
@@ -28,7 +28,7 @@ var (
ReqsForTier4 = int64(0)
ReqsForTier5 = int64(0)
- //vrfv2plus
+ // vrfv2plus
FlatFeeNativePPM = uint32(500)
FlatFeeLinkDiscountPPM = uint32(100)
NativePremiumPercentage = uint8(1)
diff --git a/core/scripts/common/vrf/setup-envs/main.go b/core/scripts/common/vrf/setup-envs/main.go
index f89b91db063..8565474ee9b 100644
--- a/core/scripts/common/vrf/setup-envs/main.go
+++ b/core/scripts/common/vrf/setup-envs/main.go
@@ -323,14 +323,14 @@ func main() {
node := node
client, app := connectToNode(&node.URL, output, node.CredsFile)
- //GET ALL JOBS
+ // GET ALL JOBS
jobIDs := getAllJobIDs(client, app, output)
- //DELETE ALL EXISTING JOBS
+ // DELETE ALL EXISTING JOBS
for _, jobID := range jobIDs {
deleteJob(jobID, client, app, output)
}
- //CREATE JOBS
+ // CREATE JOBS
switch key {
case model.VRFPrimaryNodeName:
diff --git a/core/scripts/go.mod b/core/scripts/go.mod
index 6be312a7501..13927576488 100644
--- a/core/scripts/go.mod
+++ b/core/scripts/go.mod
@@ -12,8 +12,8 @@ replace github.com/smartcontractkit/chainlink/deployment => ../../deployment
// Using a separate `require` here to avoid surrounding line changes
// creating potential merge conflicts.
require (
- github.com/smartcontractkit/chainlink/deployment v0.0.0-20250120230622-566643da09fd
- github.com/smartcontractkit/chainlink/v2 v2.0.0-20250121175436-6a8b51d8b5f5
+ github.com/smartcontractkit/chainlink/deployment v0.0.0-20250128231431-9279badae2f0
+ github.com/smartcontractkit/chainlink/v2 v2.19.0-ccip1.5.16-alpha.0.0.20250129223716-34cbaaab2d04
)
require (
@@ -34,8 +34,8 @@ require (
github.com/prometheus/client_golang v1.20.5
github.com/shopspring/decimal v1.4.0
github.com/smartcontractkit/chainlink-automation v0.8.1
- github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36
- github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3
+ github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36
+ github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13
github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919
github.com/spf13/cobra v1.8.1
@@ -45,7 +45,7 @@ require (
github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722
github.com/urfave/cli v1.22.14
go.uber.org/zap v1.27.0
- google.golang.org/protobuf v1.35.1
+ google.golang.org/protobuf v1.36.4
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.31.1
k8s.io/apimachinery v0.31.1
@@ -314,12 +314,12 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v3 v3.24.3 // indirect
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect
- github.com/smartcontractkit/chain-selectors v1.0.36 // indirect
- github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 // indirect
- github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 // indirect
+ github.com/smartcontractkit/chain-selectors v1.0.37 // indirect
+ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 // indirect
+ github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc // indirect
github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect
- github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 // indirect
+ github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a // indirect
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b // indirect
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect
diff --git a/core/scripts/go.sum b/core/scripts/go.sum
index 6a069284e75..1b9bfdb61fc 100644
--- a/core/scripts/go.sum
+++ b/core/scripts/go.sum
@@ -78,10 +78,18 @@ 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/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/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=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
+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/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -102,9 +110,17 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI=
+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=
+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=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+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.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=
@@ -126,6 +142,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
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-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+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/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
@@ -146,10 +164,16 @@ 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/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=
github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE=
+github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E=
+github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs=
github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI=
github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI=
@@ -178,12 +202,18 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI=
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo=
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo=
+github.com/aws/constructs-go/constructs/v10 v10.4.2 h1:+hDLTsFGLJmKIn0Dg20vWpKBrVnFrEWYgTEY5UiTEG8=
+github.com/aws/constructs-go/constructs/v10 v10.4.2/go.mod h1:cXsNCKDV+9eR9zYYfwy6QuE4uPFp6jsq6TtH1MwBx9w=
+github.com/aws/jsii-runtime-go v1.104.0 h1:651Sh6J2FtatfnVzlOQ3/Ye1WWPAseZ6E/tSQxEKdSI=
+github.com/aws/jsii-runtime-go v1.104.0/go.mod h1:7ZmQXxV0AAhhvv/GaHX4n6zbgA1tSRVdnQYAJbIhXHk=
github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
+github.com/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=
@@ -199,6 +229,8 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
+github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
+github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
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=
@@ -221,6 +253,12 @@ github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKz
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY=
+github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
+github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g=
+github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
+github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0=
+github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@@ -236,6 +274,10 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
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-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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
@@ -271,6 +313,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP
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/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
+github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
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.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0=
@@ -293,9 +337,14 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
+github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis=
github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA=
@@ -350,6 +399,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
+github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
+github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
@@ -360,6 +411,8 @@ github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkz
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/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=
@@ -379,6 +432,8 @@ 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/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/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=
@@ -400,6 +455,15 @@ github.com/ethereum/go-ethereum v1.14.11 h1:8nFDCUUE67rPc6AKxFj7JKaOa2W/W1Rse3oS
github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
+github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
+github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
+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/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/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.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
@@ -490,12 +554,24 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
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-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.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.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.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw=
+github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE=
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,6 +584,10 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
+github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8=
+github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
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=
@@ -536,6 +616,8 @@ github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1
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.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg=
+github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU=
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.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
@@ -606,6 +688,10 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
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.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=
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=
@@ -634,6 +720,8 @@ github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAx
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/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
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.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -659,14 +747,28 @@ github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTj
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
+github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4=
+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=
+github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU=
+github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b h1:Msqs1nc2qWMxTriDCITKl58Td+7Md/RURmUmH7RXKns=
+github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b/go.mod h1:WtWosval1KCZP9BGa42b8aVoJmVXSg0EvQXi9LDSVZQ=
+github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qvPwZO5DC6QjnAW7uKJ9YXnoUmV8c=
+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.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.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.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
@@ -687,10 +789,14 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ=
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
+github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw=
+github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
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/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.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=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -707,16 +813,24 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
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-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
+github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+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 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog=
github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
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.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=
@@ -736,7 +850,11 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
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/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=
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=
@@ -752,6 +870,8 @@ github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw=
github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w=
+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/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
@@ -843,6 +963,10 @@ 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/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+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/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
@@ -884,6 +1008,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/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/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=
@@ -942,6 +1068,8 @@ github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8Ie
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -959,6 +1087,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
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.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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=
@@ -966,6 +1096,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
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=
+github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
@@ -981,6 +1113,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
+github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@@ -994,6 +1128,10 @@ 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/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/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/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
@@ -1006,6 +1144,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
+github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -1028,16 +1168,24 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ
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=
+github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU=
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=
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
+github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
+github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
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=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+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.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
@@ -1045,12 +1193,16 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
+github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+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=
@@ -1068,6 +1220,8 @@ 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.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 v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
@@ -1083,6 +1237,10 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
+github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
+github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
+github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g=
+github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
@@ -1137,7 +1295,10 @@ github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6v
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ=
github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+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/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=
@@ -1164,24 +1325,24 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY=
-github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0=
-github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 h1:kCcrM/osIQFmHx7ZOxeGIeYAMkSmTxkOXcmqHNlXQXQ=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 h1:+/KEPuWctPObgOoEEBCnli1/H3XnjMdCY3Tn+J32XRM=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b h1:eNsqumP7VVJudA7gEcTKVFofealwbPJRinUw24uEmII=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 h1:w7w42ml8MOxdoyAZ9+og0342UkiH3deRM1V0Pj5JR5g=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4/go.mod h1:wtdAmAUMooLavbrTA7PgHg40lyDlKesxI/RR+5Xcz18=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36 h1:bS51NFGHVjkCy7yu9L2Ss4sBsCW6jpa5GuhRAdWWxzM=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc h1:WZERXv2hTYRA0NpWg79ci/ZZSxucmvkty39iUOV8d7I=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc/go.mod h1:2iGmU7fkVsy21Sw8D+OhtYekHLUlJKHzwePKcxIx3Ac=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 h1:CvDfgWoLoYPapOumE/UZCplfCu5oNmy9BuH+6V6+fJ8=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c=
github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a h1:fVtn9CDfoGF40FeqGwLvp9belfIw7VT3lgQTctFGP5E=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM=
@@ -1198,6 +1359,12 @@ github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250
github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2/go.mod h1:mMUqvS3BZfvN1OfK4OFTYf1+T0X6nwmSXJM2keaPsSM=
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug=
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ=
+github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg=
+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.5 h1:BxN9wddNLiugruN3k7nYoSMQTO0tz9qR+vILFW2l0Ps=
+github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI=
+github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8=
+github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70=
github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs=
github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA=
github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg=
@@ -1212,6 +1379,10 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
+github.com/soheilhy/cmux v0.1.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=
@@ -1300,6 +1471,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
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/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
+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.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -1322,10 +1497,14 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE=
github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o=
+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/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
+github.com/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-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
@@ -1360,8 +1539,14 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/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.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+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/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
+go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg=
+go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk=
go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -1373,6 +1558,10 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
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.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/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA=
go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00=
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg=
@@ -1421,6 +1610,8 @@ go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HY
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
+go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
+go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@@ -1447,6 +1638,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s=
+go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc=
golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1780,6 +1973,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
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.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -1901,8 +2096,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
-google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/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=
@@ -1911,6 +2106,8 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8
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=
@@ -1954,14 +2151,22 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
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.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk=
+k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U=
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.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8=
+k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w=
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.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24=
+k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM=
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=
@@ -1988,8 +2193,14 @@ 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.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.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/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go
index 203c473a4b7..278a7e54a5d 100644
--- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go
+++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go
@@ -269,7 +269,6 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) {
if err != nil {
log.Printf("workflowDON: failed to AddDON: %s", err)
}
-
}
func deployCapabilitiesRegistry(env helpers.Environment) *kcr.CapabilitiesRegistry {
diff --git a/core/scripts/keystone/src/generate_local_ocr3_config.go b/core/scripts/keystone/src/generate_local_ocr3_config.go
index c171c7f097d..68b1cade0c5 100644
--- a/core/scripts/keystone/src/generate_local_ocr3_config.go
+++ b/core/scripts/keystone/src/generate_local_ocr3_config.go
@@ -5,8 +5,7 @@ import (
"os"
"github.com/smartcontractkit/chainlink/deployment"
- "github.com/smartcontractkit/chainlink/deployment/keystone"
- ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone"
+ "github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
)
type generateLocalOCR3Config struct{}
@@ -67,7 +66,7 @@ func (g *generateLocalOCR3Config) Run(args []string) {
"CSAPublicKey": "csa_1b874ac2d54b966cec5a8358678ca6f030261aabf3372ce9dbea2d4eb9cdab3d"
}]`)
- var pubKeys []ksdeploy.NodeKeys
+ var pubKeys []changeset.NodeKeys
err := json.Unmarshal(publicKeys, &pubKeys)
if err != nil {
panic(err)
@@ -94,13 +93,13 @@ func (g *generateLocalOCR3Config) Run(args []string) {
"MaxDurationAcceptMillis": 1000,
"MaxDurationTransmitMillis": 1000,
"MaxFaultyOracles": 1}`)
- var cfg keystone.OracleConfig
+ var cfg changeset.OracleConfig
err = json.Unmarshal(config, &cfg)
if err != nil {
panic(err)
}
- ocrConfig, err := ksdeploy.GenerateOCR3Config(cfg, pubKeys, deployment.XXXGenerateTestOCRSecrets())
+ ocrConfig, err := changeset.GenerateOCR3Config(cfg, pubKeys, deployment.XXXGenerateTestOCRSecrets())
if err != nil {
panic(err)
}
diff --git a/core/scripts/vrfv2/revert-reason/main.go b/core/scripts/vrfv2/revert-reason/main.go
index 20f3cd68986..60414659204 100644
--- a/core/scripts/vrfv2/revert-reason/main.go
+++ b/core/scripts/vrfv2/revert-reason/main.go
@@ -21,7 +21,7 @@ func main() {
ec, err := ethclient.Dial("TODO")
panicErr(err)
txHash := "0xedeeecf6bd763ecc82b5dff31e073af9cc4cf8a4b47708df526ba61cf0201d25" // non-custom on goerli
- //txHash := "0x6ec8a69657600786f0b31726f36287e80196029e60f8365528d4d540a6f70763" // custom error on mainnet
+ // txHash := "0x6ec8a69657600786f0b31726f36287e80196029e60f8365528d4d540a6f70763" // custom error on mainnet
tx, _, err := ec.TransactionByHash(context.Background(), gethCommon.HexToHash(txHash))
panicErr(err)
re, err := ec.TransactionReceipt(context.Background(), gethCommon.HexToHash(txHash))
diff --git a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
index f392a35f246..b56e423f0a3 100644
--- a/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
+++ b/core/scripts/vrfv2/testnet/v2scripts/super_scripts.go
@@ -296,7 +296,7 @@ func VRFV2DeployUniverse(
if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
fmt.Println("\nRegistering proving key...")
- //NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
+ // NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
// easily withdraw funds from Coordinator contract back to EOA account
RegisterCoordinatorProvingKey(e, *coordinator, vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, vrfKeyRegistrationConfig.RegisterAgainstAddress)
@@ -354,19 +354,19 @@ func VRFV2DeployUniverse(
formattedVrfPrimaryJobSpec := fmt.Sprintf(
jobs.VRFV2JobFormatted,
- contractAddresses.CoordinatorAddress, //coordinatorAddress
- contractAddresses.BatchCoordinatorAddress, //batchCoordinatorAddress
- coordinatorJobSpecConfig.BatchFulfillmentEnabled, //batchFulfillmentEnabled
- coordinatorJobSpecConfig.BatchFulfillmentGasMultiplier, //batchFulfillmentGasMultiplier
- coordinatorJobSpecConfig.RevertsPipelineEnabled, //revertsPipelineEnabled
- compressedPkHex, //publicKey
- coordinatorConfig.MinConfs, //minIncomingConfirmations
- e.ChainID, //evmChainID
- strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), //fromAddresses
- coordinatorJobSpecConfig.PollPeriod, //pollPeriod
- coordinatorJobSpecConfig.RequestTimeout, //requestTimeout
+ contractAddresses.CoordinatorAddress, // coordinatorAddress
+ contractAddresses.BatchCoordinatorAddress, // batchCoordinatorAddress
+ coordinatorJobSpecConfig.BatchFulfillmentEnabled, // batchFulfillmentEnabled
+ coordinatorJobSpecConfig.BatchFulfillmentGasMultiplier, // batchFulfillmentGasMultiplier
+ coordinatorJobSpecConfig.RevertsPipelineEnabled, // revertsPipelineEnabled
+ compressedPkHex, // publicKey
+ coordinatorConfig.MinConfs, // minIncomingConfirmations
+ e.ChainID, // evmChainID
+ strings.Join(util.MapToAddressArr(nodesMap[model.VRFPrimaryNodeName].SendingKeys), "\",\""), // fromAddresses
+ coordinatorJobSpecConfig.PollPeriod, // pollPeriod
+ coordinatorJobSpecConfig.RequestTimeout, // requestTimeout
contractAddresses.CoordinatorAddress,
- coordinatorJobSpecConfig.EstimateGasMultiplier, //estimateGasMultiplier
+ coordinatorJobSpecConfig.EstimateGasMultiplier, // estimateGasMultiplier
simulationBlock,
func() string {
if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
@@ -387,19 +387,19 @@ func VRFV2DeployUniverse(
formattedVrfBackupJobSpec := fmt.Sprintf(
jobs.VRFV2JobFormatted,
- contractAddresses.CoordinatorAddress, //coordinatorAddress
- contractAddresses.BatchCoordinatorAddress, //batchCoordinatorAddress
- coordinatorJobSpecConfig.BatchFulfillmentEnabled, //batchFulfillmentEnabled
- coordinatorJobSpecConfig.BatchFulfillmentGasMultiplier, //batchFulfillmentGasMultiplier
- coordinatorJobSpecConfig.RevertsPipelineEnabled, //revertsPipelineEnabled
- compressedPkHex, //publicKey
- 100, //minIncomingConfirmations
- e.ChainID, //evmChainID
- strings.Join(util.MapToAddressArr(nodesMap[model.VRFBackupNodeName].SendingKeys), "\",\""), //fromAddresses
- coordinatorJobSpecConfig.PollPeriod, //pollPeriod
- coordinatorJobSpecConfig.RequestTimeout, //requestTimeout
+ contractAddresses.CoordinatorAddress, // coordinatorAddress
+ contractAddresses.BatchCoordinatorAddress, // batchCoordinatorAddress
+ coordinatorJobSpecConfig.BatchFulfillmentEnabled, // batchFulfillmentEnabled
+ coordinatorJobSpecConfig.BatchFulfillmentGasMultiplier, // batchFulfillmentGasMultiplier
+ coordinatorJobSpecConfig.RevertsPipelineEnabled, // revertsPipelineEnabled
+ compressedPkHex, // publicKey
+ 100, // minIncomingConfirmations
+ e.ChainID, // evmChainID
+ strings.Join(util.MapToAddressArr(nodesMap[model.VRFBackupNodeName].SendingKeys), "\",\""), // fromAddresses
+ coordinatorJobSpecConfig.PollPeriod, // pollPeriod
+ coordinatorJobSpecConfig.RequestTimeout, // requestTimeout
contractAddresses.CoordinatorAddress,
- coordinatorJobSpecConfig.EstimateGasMultiplier, //estimateGasMultiplier
+ coordinatorJobSpecConfig.EstimateGasMultiplier, // estimateGasMultiplier
simulationBlock,
func() string {
if keys := nodesMap[model.VRFPrimaryNodeName].SendingKeys; len(keys) > 0 {
@@ -420,33 +420,33 @@ func VRFV2DeployUniverse(
formattedBHSJobSpec := fmt.Sprintf(
jobs.BHSJobFormatted,
- contractAddresses.CoordinatorAddress, //coordinatorAddress
- bhsJobSpecConfig.WaitBlocks, //waitBlocks
- bhsJobSpecConfig.LookBackBlocks, //lookbackBlocks
- contractAddresses.BhsContractAddress, //bhs address
+ contractAddresses.CoordinatorAddress, // coordinatorAddress
+ bhsJobSpecConfig.WaitBlocks, // waitBlocks
+ bhsJobSpecConfig.LookBackBlocks, // lookbackBlocks
+ contractAddresses.BhsContractAddress, // bhs address
bhsJobSpecConfig.PollPeriod,
bhsJobSpecConfig.RunTimeout,
- e.ChainID, //chain id
- strings.Join(util.MapToAddressArr(nodesMap[model.BHSNodeName].SendingKeys), "\",\""), //sending addresses
+ e.ChainID, // chain id
+ strings.Join(util.MapToAddressArr(nodesMap[model.BHSNodeName].SendingKeys), "\",\""), // sending addresses
)
formattedBHSBackupJobSpec := fmt.Sprintf(
jobs.BHSJobFormatted,
- contractAddresses.CoordinatorAddress, //coordinatorAddress
- 100, //waitBlocks
- 200, //lookbackBlocks
- contractAddresses.BhsContractAddress, //bhs adreess
- e.ChainID, //chain id
- strings.Join(util.MapToAddressArr(nodesMap[model.BHSBackupNodeName].SendingKeys), "\",\""), //sending addresses
+ contractAddresses.CoordinatorAddress, // coordinatorAddress
+ 100, // waitBlocks
+ 200, // lookbackBlocks
+ contractAddresses.BhsContractAddress, // bhs adreess
+ e.ChainID, // chain id
+ strings.Join(util.MapToAddressArr(nodesMap[model.BHSBackupNodeName].SendingKeys), "\",\""), // sending addresses
)
formattedBHFJobSpec := fmt.Sprintf(
jobs.BHFJobFormatted,
- contractAddresses.CoordinatorAddress, //coordinatorAddress
- contractAddresses.BhsContractAddress, //bhs adreess
- contractAddresses.BatchBHSAddress, //batchBHS
- e.ChainID, //chain id
- strings.Join(util.MapToAddressArr(nodesMap[model.BHFNodeName].SendingKeys), "\",\""), //sending addresses
+ contractAddresses.CoordinatorAddress, // coordinatorAddress
+ contractAddresses.BhsContractAddress, // bhs adreess
+ contractAddresses.BatchBHSAddress, // batchBHS
+ e.ChainID, // chain id
+ strings.Join(util.MapToAddressArr(nodesMap[model.BHFNodeName].SendingKeys), "\",\""), // sending addresses
)
fmt.Println(
diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
index dd0186144d4..1f7294e574e 100644
--- a/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
+++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/super_scripts.go
@@ -755,7 +755,7 @@ func VRFV2PlusDeployUniverse(e helpers.Environment,
if len(vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey) > 0 {
fmt.Println("\nRegistering proving key...")
- //NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
+ // NOTE - register proving key against EOA account, and not against Oracle's sending address in other to be able
// easily withdraw funds from Coordinator contract back to EOA account
RegisterCoordinatorProvingKey(e, *coordinator, vrfKeyRegistrationConfig.VRFKeyUncompressedPubKey, provingKeyMaxGasPrice)
diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go
index 5b89794eb6e..9aa589a98c2 100644
--- a/core/services/blockhashstore/bhs_test.go
+++ b/core/services/blockhashstore/bhs_test.go
@@ -19,18 +19,19 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
"github.com/smartcontractkit/chainlink/v2/core/utils"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/types"
)
func TestStoreRotatesFromAddresses(t *testing.T) {
ctx := testutils.Context(t)
db := pgtest.NewSqlxDB(t)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
cfg := configtest.NewTestGeneralConfig(t)
kst := cltest.NewKeyStore(t, db)
require.NoError(t, kst.Unlock(ctx, cltest.Password))
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go
index be32bd21e66..8f006d6a708 100644
--- a/core/services/blockhashstore/delegate_test.go
+++ b/core/services/blockhashstore/delegate_test.go
@@ -49,7 +49,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) {
t.Helper()
lggr, logs := logger.TestLoggerObserved(t, zapcore.DebugLevel)
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Feature.LogPoller = func(b bool) *bool { return &b }(true)
})
@@ -63,7 +63,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) {
legacyChains := evmtest.NewLegacyChains(
t,
evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go
index 1b1b82d2118..e92847ccb34 100644
--- a/core/services/chainlink/application.go
+++ b/core/services/chainlink/application.go
@@ -30,11 +30,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"
+ "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/remote"
remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types"
@@ -197,6 +197,8 @@ type ApplicationOpts struct {
CapabilitiesDispatcher remotetypes.Dispatcher
CapabilitiesPeerWrapper p2ptypes.PeerWrapper
NewOracleFactoryFn standardcapabilities.NewOracleFactoryFn
+ FetcherFunc syncer.FetcherFunc
+ FetcherFactoryFn compute.FetcherFactory
}
type Heartbeat struct {
@@ -358,8 +360,17 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
srvcs = append(srvcs, wfLauncher, registrySyncer)
if cfg.Capabilities().WorkflowRegistry().Address() != "" {
- if gatewayConnectorWrapper == nil {
- return nil, errors.New("unable to create workflow registry syncer without gateway connector")
+ lggr := globalLogger.Named("WorkflowRegistrySyncer")
+ var fetcherFunc syncer.FetcherFunc
+ if opts.FetcherFunc == nil {
+ if gatewayConnectorWrapper == nil {
+ return nil, errors.New("unable to create workflow registry syncer without gateway connector")
+ }
+ fetcher := syncer.NewFetcherService(lggr, gatewayConnectorWrapper)
+ fetcherFunc = fetcher.Fetch
+ srvcs = append(srvcs, fetcher)
+ } else {
+ fetcherFunc = opts.FetcherFunc
}
err = keyStore.Workflow().EnsureKey(context.Background())
@@ -375,13 +386,10 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
return nil, fmt.Errorf("expected 1 key, got %d", len(keys))
}
- lggr := globalLogger.Named("WorkflowRegistrySyncer")
- fetcher := syncer.NewFetcherService(lggr, gatewayConnectorWrapper)
-
eventHandler := syncer.NewEventHandler(
lggr,
syncer.NewWorkflowRegistryDS(opts.DS, globalLogger),
- fetcher.Fetch,
+ fetcherFunc,
workflowstore.NewDBStore(opts.DS, lggr, clockwork.NewRealClock()),
opts.CapabilitiesRegistry,
custmsg.NewLabeler(),
@@ -411,7 +419,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
workflowDonNotifier,
)
- srvcs = append(srvcs, fetcher, wfSyncer)
+ srvcs = append(srvcs, wfSyncer)
}
}
} else {
@@ -614,7 +622,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
)
// Flux monitor requires ethereum just to boot, silence errors with a null delegate
- if !cfg.EVMRPCEnabled() {
+ if !cfg.EVMConfigs().RPCEnabled() {
delegates[job.FluxMonitor] = &job.NullDelegate{Type: job.FluxMonitor}
} else {
delegates[job.FluxMonitor] = fluxmonitorv2.NewDelegate(
@@ -655,6 +663,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) {
keyStore,
peerWrapper,
opts.NewOracleFactoryFn,
+ opts.FetcherFactoryFn,
)
if cfg.OCR().Enabled() {
diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go
index ea27d28d28b..65d9126b3d6 100644
--- a/core/services/chainlink/config_general.go
+++ b/core/services/chainlink/config_general.go
@@ -195,6 +195,9 @@ func (o *GeneralConfigOpts) parse() (err error) {
}
func (g *generalConfig) EVMConfigs() evmcfg.EVMConfigs {
+ if g.c.EVM == nil {
+ return evmcfg.EVMConfigs{} // return empty to pass nil check
+ }
return g.c.EVM
}
@@ -316,17 +319,6 @@ func (g *generalConfig) EVMEnabled() bool {
return false
}
-func (g *generalConfig) EVMRPCEnabled() bool {
- for _, c := range g.c.EVM {
- if c.IsEnabled() {
- if len(c.Nodes) > 0 {
- return true
- }
- }
- }
- return false
-}
-
func (g *generalConfig) SolanaEnabled() bool {
for _, c := range g.c.Solana {
if c.IsEnabled() {
diff --git a/core/services/chainlink/config_general_test.go b/core/services/chainlink/config_general_test.go
index 3f02b880baf..22a5a131e5a 100644
--- a/core/services/chainlink/config_general_test.go
+++ b/core/services/chainlink/config_general_test.go
@@ -23,7 +23,7 @@ func TestTOMLGeneralConfig_Defaults(t *testing.T) {
config, err := GeneralConfigOpts{}.New()
require.NoError(t, err)
assert.Equal(t, (*url.URL)(nil), config.WebServer().BridgeResponseURL())
- assert.False(t, config.EVMRPCEnabled())
+ assert.False(t, config.EVMConfigs().RPCEnabled())
assert.False(t, config.EVMEnabled())
assert.False(t, config.CosmosEnabled())
assert.False(t, config.SolanaEnabled())
diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go
index 44b272ba93a..007f1e3e2db 100644
--- a/core/services/chainlink/mocks/general_config.go
+++ b/core/services/chainlink/mocks/general_config.go
@@ -602,51 +602,6 @@ func (_c *GeneralConfig_EVMEnabled_Call) RunAndReturn(run func() bool) *GeneralC
return _c
}
-// EVMRPCEnabled provides a mock function with no fields
-func (_m *GeneralConfig) EVMRPCEnabled() bool {
- ret := _m.Called()
-
- if len(ret) == 0 {
- panic("no return value specified for EVMRPCEnabled")
- }
-
- var r0 bool
- if rf, ok := ret.Get(0).(func() bool); ok {
- r0 = rf()
- } else {
- r0 = ret.Get(0).(bool)
- }
-
- return r0
-}
-
-// GeneralConfig_EVMRPCEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EVMRPCEnabled'
-type GeneralConfig_EVMRPCEnabled_Call struct {
- *mock.Call
-}
-
-// EVMRPCEnabled is a helper method to define mock.On call
-func (_e *GeneralConfig_Expecter) EVMRPCEnabled() *GeneralConfig_EVMRPCEnabled_Call {
- return &GeneralConfig_EVMRPCEnabled_Call{Call: _e.mock.On("EVMRPCEnabled")}
-}
-
-func (_c *GeneralConfig_EVMRPCEnabled_Call) Run(run func()) *GeneralConfig_EVMRPCEnabled_Call {
- _c.Call.Run(func(args mock.Arguments) {
- run()
- })
- return _c
-}
-
-func (_c *GeneralConfig_EVMRPCEnabled_Call) Return(_a0 bool) *GeneralConfig_EVMRPCEnabled_Call {
- _c.Call.Return(_a0)
- return _c
-}
-
-func (_c *GeneralConfig_EVMRPCEnabled_Call) RunAndReturn(run func() bool) *GeneralConfig_EVMRPCEnabled_Call {
- _c.Call.Return(run)
- return _c
-}
-
// Feature provides a mock function with no fields
func (_m *GeneralConfig) Feature() config.Feature {
ret := _m.Called()
diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go
index a3e9e2ad205..379bc658b0b 100644
--- a/core/services/chainlink/relayer_chain_interoperators.go
+++ b/core/services/chainlink/relayer_chain_interoperators.go
@@ -128,7 +128,7 @@ func InitEVM(ctx context.Context, factory RelayerFactory, config EVMFactoryConfi
op.loopRelayers[id] = a
legacyMap[id.ChainID] = a.Chain()
}
- op.legacyChains.EVMChains = legacyevm.NewLegacyChains(legacyMap, config.AppConfig.EVMConfigs())
+ op.legacyChains.EVMChains = legacyevm.NewLegacyChains(legacyMap, config.ChainConfigs)
return nil
}
}
diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go
index 26d6442132f..3fb98900b80 100644
--- a/core/services/chainlink/relayer_chain_interoperators_test.go
+++ b/core/services/chainlink/relayer_chain_interoperators_test.go
@@ -213,7 +213,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
initFuncs: []chainlink.CoreRelayerChainInitFunc{
chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
@@ -289,7 +289,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) {
TOMLConfigs: cfg.SolanaConfigs()}),
chainlink.InitEVM(testctx, factory, chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go
index f3c4544159e..392274703c0 100644
--- a/core/services/chainlink/relayer_factory.go
+++ b/core/services/chainlink/relayer_factory.go
@@ -328,7 +328,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] = cosmos.NewRelayer(lggr, chain)
+ relayers[relayID] = relay.NewServerAdapter(cosmos.NewRelayer(lggr, chain))
}
}
return relayers, nil
diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go
index 80469a03636..4116ce57732 100644
--- a/core/services/directrequest/delegate_test.go
+++ b/core/services/directrequest/delegate_test.go
@@ -33,11 +33,12 @@ 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"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
ubig "github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
func TestDelegate_ServicesForSpec(t *testing.T) {
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
runner := pipeline_mocks.NewRunner(t)
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
@@ -46,7 +47,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) {
keyStore := cltest.NewKeyStore(t, db)
mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t))
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
@@ -84,7 +85,7 @@ type DirectRequestUniverse struct {
}
func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfig, specF func(spec *job.Job)) *DirectRequestUniverse {
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
broadcaster := log_mocks.NewBroadcaster(t)
runner := pipeline_mocks.NewRunner(t)
broadcaster.On("AddDependents", 1)
@@ -94,7 +95,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi
db := pgtest.NewSqlxDB(t)
keyStore := cltest.NewKeyStore(t, db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go
index 0b042e98d79..f22d3a72c9d 100644
--- a/core/services/feeds/orm_test.go
+++ b/core/services/feeds/orm_test.go
@@ -1736,7 +1736,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job {
pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns())
bridgeORM = bridges.NewORM(db)
legacyChains = evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go
index 6bbfe1fe035..f99fde65b63 100644
--- a/core/services/feeds/service.go
+++ b/core/services/feeds/service.go
@@ -24,6 +24,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2"
+ "github.com/smartcontractkit/chainlink/v2/core/services/gateway"
"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/ocrkey"
@@ -31,6 +32,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr"
ocr2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap"
+ "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities"
"github.com/smartcontractkit/chainlink/v2/core/services/streams"
"github.com/smartcontractkit/chainlink/v2/core/services/workflows"
"github.com/smartcontractkit/chainlink/v2/core/utils/crypto"
@@ -891,6 +893,20 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error {
if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) {
return fmt.Errorf("failed while checking for existing ccip job: %w", txerr)
}
+ case job.StandardCapabilities:
+ existingJobID, txerr = tx.jobORM.FindStandardCapabilityJobID(ctx, *j.StandardCapabilitiesSpec)
+ // 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 standard capabilities job: %w", txerr)
+ }
+ case job.Gateway:
+ existingJobID, txerr = tx.jobORM.FindGatewayJobID(ctx, *j.GatewaySpec)
+ // 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 gateway job: %w", txerr)
+ }
case job.Stream:
existingJobID, txerr = tx.jobORM.FindJobIDByStreamID(ctx, *j.StreamID)
// Return an error if the repository errors. If there is a not found
@@ -1304,6 +1320,10 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error
js, err = ccip.ValidatedCCIPSpec(spec)
case job.Stream:
js, err = streams.ValidatedStreamSpec(spec)
+ case job.Gateway:
+ js, err = gateway.ValidatedGatewaySpec(spec)
+ case job.StandardCapabilities:
+ js, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(spec)
default:
return nil, errors.Errorf("unknown job type: %s", jobType)
}
diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go
index 055423c1dc9..24738680fb3 100644
--- a/core/services/feeds/service_test.go
+++ b/core/services/feeds/service_test.go
@@ -226,7 +226,7 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s *
keyStore := new(ksmocks.Master)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: gcfg,
+ ChainConfigs: gcfg.EVMConfigs(),
DatabaseConfig: gcfg.Database(),
FeatureConfig: gcfg.Feature(),
ListenerConfig: gcfg.Database().Listener(),
diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go
index 765c1908009..5cbab946b45 100644
--- a/core/services/functions/listener_test.go
+++ b/core/services/functions/listener_test.go
@@ -44,6 +44,7 @@ import (
sync_mocks "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/mocks"
"github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
"github.com/smartcontractkit/chainlink/v2/core/services/telemetry"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
)
type FunctionsListenerUniverse struct {
@@ -78,7 +79,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe
cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].MinIncomingConfirmations = ptr[uint32](1)
})
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
broadcaster := log_mocks.NewBroadcaster(t)
broadcaster.On("AddDependents", 1)
mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t))
@@ -86,7 +87,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe
db := pgtest.NewSqlxDB(t)
kst := cltest.NewKeyStore(t, db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/headreporter/prometheus_reporter_test.go
index ea8ffa732f8..a6a728738ba 100644
--- a/core/services/headreporter/prometheus_reporter_test.go
+++ b/core/services/headreporter/prometheus_reporter_test.go
@@ -17,10 +17,10 @@ import (
"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/evmtest"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/headreporter"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/gas"
)
@@ -121,7 +121,7 @@ func Test_PrometheusReporter(t *testing.T) {
func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainContainer {
config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t)
keyStore := cltest.NewKeyStore(t, db).Eth()
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config.ChainType(), ethClient.ConfiguredChainID(), evmConfig.GasEstimator(), nil)
require.NoError(t, err)
lggr := logger.TestLogger(t)
@@ -157,7 +157,7 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon
}
func newLegacyChainContainerWithNullTxm(t *testing.T) legacyevm.LegacyChainContainer {
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
txm := &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("TXM disabled for chain %d", ethClient.ConfiguredChainID())}
cfg := configtest.NewGeneralConfig(t, nil)
return cltest.NewLegacyChainsWithMockChainAndTxManager(t, ethClient, cfg, txm)
diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go
index 6dd72b3d759..fae03ed6d43 100644
--- a/core/services/job/helpers_test.go
+++ b/core/services/job/helpers_test.go
@@ -25,6 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
)
const (
@@ -211,12 +212,12 @@ 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)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
DB: db,
- Client: evmtest.NewEthClientMockWithDefaultChain(t),
+ Client: clienttest.NewClientWithDefaultChainID(t),
KeyStore: keyStore.Eth(),
})
_, err := ocr.ValidatedOracleSpecToml(cfg, legacyChains, s)
diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go
index 6edf76118ce..cd010c76215 100644
--- a/core/services/job/job_orm_test.go
+++ b/core/services/job/job_orm_test.go
@@ -31,6 +31,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/blockheaderfeeder"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/directrequest"
+ "github.com/smartcontractkit/chainlink/v2/core/services/gateway"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
@@ -40,6 +41,7 @@ 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"
+ "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities"
"github.com/smartcontractkit/chainlink/v2/core/services/streams"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
@@ -377,7 +379,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) {
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -803,7 +805,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) {
JobID: externalJobID.UUID.String(),
})
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1080,7 +1082,7 @@ func Test_FindJobs(t *testing.T) {
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1171,7 +1173,7 @@ func Test_FindJob(t *testing.T) {
externalJobID := uuid.New()
_, address := cltest.MustInsertRandomKey(t, keyStore.Eth())
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1409,7 +1411,7 @@ func Test_FindPipelineRuns(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1479,7 +1481,7 @@ func Test_PipelineRunsByJobID(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1548,7 +1550,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1669,7 +1671,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -1855,7 +1857,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) {
pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
bridgesORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -2175,7 +2177,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
emptyTransmitterAddress := `
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = ''
`
jb, err = ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), baseJobSpec+emptyTransmitterAddress, nil)
@@ -2187,7 +2189,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
metaNotSliceDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
key1 = 'val1'
@@ -2202,7 +2204,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
hintNotValidDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
hint = ['some-invalid-hint']
@@ -2217,7 +2219,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
invalidRefundFormatDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
hint = ['calldata','logs']
@@ -2232,7 +2234,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
invalidRefundAddressFormatDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
hint = ['calldata','logs']
@@ -2247,7 +2249,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
invalidRefundPercentFormatDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
hint = ['calldata','logs']
@@ -2262,7 +2264,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
invalidRefundPercentTotalFormatDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
hint = ['calldata','logs']
@@ -2277,7 +2279,7 @@ func TestORM_CreateJob_OCR2_With_DualTransmission(t *testing.T) {
completeDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
key1 = ['val1']
@@ -2330,7 +2332,7 @@ func TestORM_CreateJob_KeyLocking(t *testing.T) {
completeDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
key1 = ['val1']
@@ -2351,7 +2353,7 @@ func TestORM_CreateJob_KeyLocking(t *testing.T) {
completeDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
key1 = ['val1']
@@ -2385,7 +2387,7 @@ func TestORM_CreateJob_KeyLocking(t *testing.T) {
completeDualTransmissionSpec := fmt.Sprintf(`
enableDualTransmission=true
[relayConfig.dualTransmission]
- contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
+ contractAddress = '0x613a38AC1659769640aaE063C651F48E0250454C'
transmitterAddress = '%s'
[relayConfig.dualTransmission.meta]
key1 = ['val1']
@@ -2402,3 +2404,143 @@ func TestORM_CreateJob_KeyLocking(t *testing.T) {
require.ErrorContains(t, jobORM.CreateJob(ctx, &jb), "cannot be a secondary transmitter address because it's used a primary transmitter in another job")
})
}
+
+func Test_FindGatewayJobID(t *testing.T) {
+ t.Parallel()
+ ctx := testutils.Context(t)
+
+ config := configtest.NewTestGeneralConfig(t)
+ db := pgtest.NewSqlxDB(t)
+
+ keyStore := cltest.NewKeyStore(t, db)
+ err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)
+ require.NoError(t, err, "failed to add OCR key")
+
+ pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
+ bridgesORM := bridges.NewORM(db)
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore)
+
+ gatewayJob, err := gateway.ValidatedGatewaySpec(testspecs.GetGatewaySpec())
+ require.NoError(t, err, "failed to validate gateway spec")
+
+ err = orm.CreateJob(ctx, &gatewayJob)
+ require.NoError(t, err, "failed to create gateway job")
+ var jobSpec job.Job
+ err = db.Get(&jobSpec, "SELECT * FROM jobs")
+ require.NoError(t, err, "failed to get gateway job from db")
+
+ // find only by auth gateway id
+ gatewayJobSpec := job.GatewaySpec{
+ GatewayConfig: job.JSONConfig{
+ "ConnectionManagerConfig": map[string]interface{}{
+ "AuthGatewayId": "gateway",
+ },
+ },
+ }
+ id, err := orm.FindGatewayJobID(ctx, gatewayJobSpec)
+ require.NoError(t, err, "failed to find gateway job by auth gateway id")
+ require.Equal(t, jobSpec.ID, id, "mismatch job id")
+}
+
+func Test_FindGatewayJobID_NoMatch(t *testing.T) {
+ t.Parallel()
+ ctx := testutils.Context(t)
+
+ config := configtest.NewTestGeneralConfig(t)
+ db := pgtest.NewSqlxDB(t)
+
+ keyStore := cltest.NewKeyStore(t, db)
+ err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)
+ require.NoError(t, err, "failed to add OCR key")
+
+ pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
+ bridgesORM := bridges.NewORM(db)
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore)
+
+ gatewayJob, err := gateway.ValidatedGatewaySpec(testspecs.GetGatewaySpec())
+ require.NoError(t, err, "failed to validate gateway spec")
+
+ err = orm.CreateJob(ctx, &gatewayJob)
+ require.NoError(t, err, "failed to create gateway job")
+ var jobSpec job.Job
+ err = db.Get(&jobSpec, "SELECT * FROM jobs")
+ require.NoError(t, err, "failed to get gateway job from db")
+
+ // different auth gateway id
+ gatewayJobSpec := job.GatewaySpec{
+ GatewayConfig: job.JSONConfig{
+ "ConnectionManagerConfig": map[string]interface{}{
+ "AuthGatewayId": "another_gateway",
+ },
+ },
+ }
+ id, err := orm.FindGatewayJobID(ctx, gatewayJobSpec)
+ require.Error(t, err, "found gateway job by auth gateway id")
+ require.Equal(t, int32(0), id, "found non-zero job id")
+}
+
+func Test_FindStandardCapabilityJobID(t *testing.T) {
+ t.Parallel()
+ ctx := testutils.Context(t)
+
+ config := configtest.NewTestGeneralConfig(t)
+ db := pgtest.NewSqlxDB(t)
+
+ keyStore := cltest.NewKeyStore(t, db)
+ err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)
+ require.NoError(t, err, "failed to add OCR key")
+
+ pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
+ bridgesORM := bridges.NewORM(db)
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore)
+
+ stdJob, err := standardcapabilities.ValidatedStandardCapabilitiesSpec(testspecs.GetStandardCapabilitySpec())
+ require.NoError(t, err, "failed to validate standard capabilities spec")
+
+ err = orm.CreateJob(ctx, &stdJob)
+ require.NoError(t, err, "failed to create standard capabilities job")
+ var jobSpec job.Job
+ err = db.Get(&jobSpec, "SELECT * FROM jobs")
+ require.NoError(t, err, "failed to get standard capabilities job from db")
+
+ stdCapJobSpec := job.StandardCapabilitiesSpec{
+ Command: "/home/capabilities/some_capability_linux_amd64",
+ }
+
+ id, err := orm.FindStandardCapabilityJobID(ctx, stdCapJobSpec)
+ require.NoError(t, err, "failed to find standard capabilities by command")
+ require.Equal(t, jobSpec.ID, id, "mismatch job id")
+}
+
+func Test_FindStandardCapabilityJobID_NoMatch(t *testing.T) {
+ t.Parallel()
+ ctx := testutils.Context(t)
+
+ config := configtest.NewTestGeneralConfig(t)
+ db := pgtest.NewSqlxDB(t)
+
+ keyStore := cltest.NewKeyStore(t, db)
+ err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)
+ require.NoError(t, err, "failed to add OCR key")
+
+ pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
+ bridgesORM := bridges.NewORM(db)
+ orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore)
+
+ stdJob, err := standardcapabilities.ValidatedStandardCapabilitiesSpec(testspecs.GetStandardCapabilitySpec())
+ require.NoError(t, err, "failed to validate standard capabilities spec")
+
+ err = orm.CreateJob(ctx, &stdJob)
+ require.NoError(t, err, "failed to create standard capabilities job")
+ var jobSpec job.Job
+ err = db.Get(&jobSpec, "SELECT * FROM jobs")
+ require.NoError(t, err, "failed to get standard capabilities job from db")
+
+ stdCapJobSpec := job.StandardCapabilitiesSpec{
+ Command: "/home/capabilities/some_other_capability_linux_amd64",
+ }
+
+ id, err := orm.FindStandardCapabilityJobID(ctx, stdCapJobSpec)
+ require.Error(t, err, "found standard capabilities with different command")
+ require.Equal(t, int32(0), id, "found non-zero job id")
+}
diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go
index efc30299d7d..ff24995cec9 100644
--- a/core/services/job/job_pipeline_orm_integration_test.go
+++ b/core/services/job/job_pipeline_orm_integration_test.go
@@ -21,6 +21,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
)
func clearJobsDb(t *testing.T, db *sqlx.DB) {
@@ -155,11 +156,11 @@ func TestPipelineORM_Integration(t *testing.T) {
orm := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns())
btORM := bridges.NewORM(db)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
- Client: evmtest.NewEthClientMockWithDefaultChain(t),
+ Client: clienttest.NewClientWithDefaultChainID(t),
DB: db,
KeyStore: ethKeyStore,
})
diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go
index 15e3a4e99b3..2bfd5f3fa84 100644
--- a/core/services/job/mocks/orm.go
+++ b/core/services/job/mocks/orm.go
@@ -372,6 +372,63 @@ func (_c *ORM_DismissError_Call) RunAndReturn(run func(context.Context, int64) e
return _c
}
+// FindGatewayJobID provides a mock function with given fields: ctx, spec
+func (_m *ORM) FindGatewayJobID(ctx context.Context, spec job.GatewaySpec) (int32, error) {
+ ret := _m.Called(ctx, spec)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindGatewayJobID")
+ }
+
+ var r0 int32
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, job.GatewaySpec) (int32, error)); ok {
+ return rf(ctx, spec)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, job.GatewaySpec) int32); ok {
+ r0 = rf(ctx, spec)
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, job.GatewaySpec) error); ok {
+ r1 = rf(ctx, spec)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ORM_FindGatewayJobID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindGatewayJobID'
+type ORM_FindGatewayJobID_Call struct {
+ *mock.Call
+}
+
+// FindGatewayJobID is a helper method to define mock.On call
+// - ctx context.Context
+// - spec job.GatewaySpec
+func (_e *ORM_Expecter) FindGatewayJobID(ctx interface{}, spec interface{}) *ORM_FindGatewayJobID_Call {
+ return &ORM_FindGatewayJobID_Call{Call: _e.mock.On("FindGatewayJobID", ctx, spec)}
+}
+
+func (_c *ORM_FindGatewayJobID_Call) Run(run func(ctx context.Context, spec job.GatewaySpec)) *ORM_FindGatewayJobID_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(job.GatewaySpec))
+ })
+ return _c
+}
+
+func (_c *ORM_FindGatewayJobID_Call) Return(_a0 int32, _a1 error) *ORM_FindGatewayJobID_Call {
+ _c.Call.Return(_a0, _a1)
+ return _c
+}
+
+func (_c *ORM_FindGatewayJobID_Call) RunAndReturn(run func(context.Context, job.GatewaySpec) (int32, error)) *ORM_FindGatewayJobID_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
// FindJob provides a mock function with given fields: ctx, id
func (_m *ORM) FindJob(ctx context.Context, id int32) (job.Job, error) {
ret := _m.Called(ctx, id)
@@ -1308,6 +1365,63 @@ func (_c *ORM_FindSpecErrorsByJobIDs_Call) RunAndReturn(run func(context.Context
return _c
}
+// FindStandardCapabilityJobID provides a mock function with given fields: ctx, spec
+func (_m *ORM) FindStandardCapabilityJobID(ctx context.Context, spec job.StandardCapabilitiesSpec) (int32, error) {
+ ret := _m.Called(ctx, spec)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindStandardCapabilityJobID")
+ }
+
+ var r0 int32
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, job.StandardCapabilitiesSpec) (int32, error)); ok {
+ return rf(ctx, spec)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, job.StandardCapabilitiesSpec) int32); ok {
+ r0 = rf(ctx, spec)
+ } else {
+ r0 = ret.Get(0).(int32)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, job.StandardCapabilitiesSpec) error); ok {
+ r1 = rf(ctx, spec)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ORM_FindStandardCapabilityJobID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindStandardCapabilityJobID'
+type ORM_FindStandardCapabilityJobID_Call struct {
+ *mock.Call
+}
+
+// FindStandardCapabilityJobID is a helper method to define mock.On call
+// - ctx context.Context
+// - spec job.StandardCapabilitiesSpec
+func (_e *ORM_Expecter) FindStandardCapabilityJobID(ctx interface{}, spec interface{}) *ORM_FindStandardCapabilityJobID_Call {
+ return &ORM_FindStandardCapabilityJobID_Call{Call: _e.mock.On("FindStandardCapabilityJobID", ctx, spec)}
+}
+
+func (_c *ORM_FindStandardCapabilityJobID_Call) Run(run func(ctx context.Context, spec job.StandardCapabilitiesSpec)) *ORM_FindStandardCapabilityJobID_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(job.StandardCapabilitiesSpec))
+ })
+ return _c
+}
+
+func (_c *ORM_FindStandardCapabilityJobID_Call) Return(_a0 int32, _a1 error) *ORM_FindStandardCapabilityJobID_Call {
+ _c.Call.Return(_a0, _a1)
+ return _c
+}
+
+func (_c *ORM_FindStandardCapabilityJobID_Call) RunAndReturn(run func(context.Context, job.StandardCapabilitiesSpec) (int32, error)) *ORM_FindStandardCapabilityJobID_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
// FindTaskResultByRunIDAndTaskName provides a mock function with given fields: ctx, runID, taskName
func (_m *ORM) FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) ([]byte, error) {
ret := _m.Called(ctx, runID, taskName)
diff --git a/core/services/job/models.go b/core/services/job/models.go
index d081f08bef0..1a948621e54 100644
--- a/core/services/job/models.go
+++ b/core/services/job/models.go
@@ -823,6 +823,22 @@ func (s *GatewaySpec) SetID(value string) error {
return nil
}
+// AuthGatewayID returns AuthGatewayId or empty string, if not found or it's not a string
+func (s *GatewaySpec) AuthGatewayID() string {
+ // not using config.GatewayConfig directly to avoid import cycle
+ if nsc, ok := s.GatewayConfig["ConnectionManagerConfig"]; ok {
+ if nscMap, ok := nsc.(map[string]interface{}); ok {
+ if authGatewayID, ok := nscMap["AuthGatewayId"]; ok {
+ if authGatewayIDStr, ok := authGatewayID.(string); ok {
+ return authGatewayIDStr
+ }
+ }
+ }
+ }
+
+ return ""
+}
+
// EALSpec defines the job spec for the gas station.
type EALSpec struct {
ID int32
diff --git a/core/services/job/orm.go b/core/services/job/orm.go
index d0dc0767afb..8c41bb00b0d 100644
--- a/core/services/job/orm.go
+++ b/core/services/job/orm.go
@@ -78,7 +78,10 @@ type ORM interface {
WithDataSource(source sqlutil.DataSource) ORM
FindJobIDByWorkflow(ctx context.Context, spec WorkflowSpec) (int32, error)
+ // TODO rename function to indicate it is CCIP-specific, not generic?
FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec CCIPSpec) (int32, error)
+ FindStandardCapabilityJobID(ctx context.Context, spec StandardCapabilitiesSpec) (int32, error)
+ FindGatewayJobID(ctx context.Context, spec GatewaySpec) (int32, error)
FindJobIDByStreamID(ctx context.Context, streamID uint32) (int32, error)
}
@@ -821,7 +824,7 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error {
%s
),`, q)
}
- query += `
+ query += `
deleted_job_pipeline_specs AS (
DELETE FROM job_pipeline_specs WHERE job_id IN (SELECT id FROM deleted_jobs) RETURNING pipeline_spec_id
)
@@ -1179,6 +1182,30 @@ INNER JOIN ccip_specs ccip on jobs.ccip_spec_id = ccip.id AND ccip.capability_la
return
}
+func (o *orm) FindStandardCapabilityJobID(ctx context.Context, spec StandardCapabilitiesSpec) (jobID int32, err error) {
+ stmt := `
+SELECT jobs.id FROM jobs
+INNER JOIN standardcapabilities_specs sc on jobs.standard_capabilities_spec_id = sc.id AND sc.command = $1
+`
+ err = o.ds.GetContext(ctx, &jobID, stmt, spec.Command)
+ if err != nil && !errors.Is(err, sql.ErrNoRows) {
+ err = fmt.Errorf("error searching for job for standardcapabilities (command) ('%s'): %w", spec.Command, err)
+ }
+ return
+}
+
+func (o *orm) FindGatewayJobID(ctx context.Context, spec GatewaySpec) (jobID int32, err error) {
+ stmt := `
+SELECT jobs.id FROM jobs
+INNER JOIN gateway_specs gs on jobs.gateway_spec_id = gs.id
+WHERE gs.gateway_config @> jsonb_build_object('ConnectionManagerConfig', jsonb_build_object('AuthGatewayId', $1::text));`
+ err = o.ds.GetContext(ctx, &jobID, stmt, spec.AuthGatewayID())
+ if err != nil && !errors.Is(err, sql.ErrNoRows) {
+ err = fmt.Errorf("error searching for job for gateway (ConnectionManagerConfig.AuthGatewayId) ('%s'): %w", spec.AuthGatewayID(), 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 1caa1461dc8..03f71e6cf09 100644
--- a/core/services/job/runner_integration_test.go
+++ b/core/services/job/runner_integration_test.go
@@ -86,7 +86,7 @@ func TestRunner(t *testing.T) {
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
Client: ethClient,
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -570,7 +570,7 @@ answer1 [type=median index=0];
legacyChains2 := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
Client: ethClient,
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go
index b28abcc9208..7e3f634228e 100644
--- a/core/services/job/spawner_test.go
+++ b/core/services/job/spawner_test.go
@@ -101,7 +101,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) {
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
Client: ethClient,
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
@@ -286,7 +286,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) {
testopts := evmtest.TestChainOpts{
DB: db,
Client: ethClient,
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
diff --git a/core/services/keeper/registry1_1_synchronizer_test.go b/core/services/keeper/registry1_1_synchronizer_test.go
index b5d5bae5948..2ec2b18e88d 100644
--- a/core/services/keeper/registry1_1_synchronizer_test.go
+++ b/core/services/keeper/registry1_1_synchronizer_test.go
@@ -18,7 +18,6 @@ import (
registry1_1 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"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/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
@@ -73,7 +72,7 @@ func mockRegistry1_1(
func Test_LogListenerOpts1_1(t *testing.T) {
db := pgtest.NewSqlxDB(t)
korm := keeper.NewORM(db, logger.TestLogger(t))
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address())
contractAddress := j.KeeperSpec.ContractAddress.Address()
diff --git a/core/services/keeper/registry1_2_synchronizer_test.go b/core/services/keeper/registry1_2_synchronizer_test.go
index 81af282d8c9..e7d915d565c 100644
--- a/core/services/keeper/registry1_2_synchronizer_test.go
+++ b/core/services/keeper/registry1_2_synchronizer_test.go
@@ -17,7 +17,6 @@ import (
registry1_2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"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/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
@@ -95,7 +94,7 @@ func mockRegistry1_2(
func Test_LogListenerOpts1_2(t *testing.T) {
db := pgtest.NewSqlxDB(t)
korm := keeper.NewORM(db, logger.TestLogger(t))
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address())
contractAddress := j.KeeperSpec.ContractAddress.Address()
diff --git a/core/services/keeper/registry1_3_synchronizer_test.go b/core/services/keeper/registry1_3_synchronizer_test.go
index dd4be5f3593..210b7092fbb 100644
--- a/core/services/keeper/registry1_3_synchronizer_test.go
+++ b/core/services/keeper/registry1_3_synchronizer_test.go
@@ -18,7 +18,6 @@ import (
registry1_3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3"
"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
"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/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/keeper"
@@ -97,7 +96,7 @@ func mockRegistry1_3(
func Test_LogListenerOpts1_3(t *testing.T) {
db := pgtest.NewSqlxDB(t)
korm := keeper.NewORM(db, logger.TestLogger(t))
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address())
contractAddress := j.KeeperSpec.ContractAddress.Address()
diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go
index 8a6b01b3394..34fff6095ca 100644
--- a/core/services/keeper/registry_synchronizer_helper_test.go
+++ b/core/services/keeper/registry_synchronizer_helper_test.go
@@ -38,7 +38,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) (
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewGeneralConfig(t, nil)
korm := keeper.NewORM(db, logger.TestLogger(t))
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
keyStore := cltest.NewKeyStore(t, db)
lbMock := logmocks.NewBroadcaster(t)
lbMock.On("AddDependents", 1).Maybe()
@@ -47,7 +47,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) (
DB: db,
Client: ethClient,
LogBroadcaster: lbMock,
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go
index bd2d7640f96..3a881d52265 100644
--- a/core/services/keeper/upkeep_executer_test.go
+++ b/core/services/keeper/upkeep_executer_test.go
@@ -85,7 +85,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain
DB: db,
Client: ethClient,
KeyStore: keyStore.Eth(),
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/llo/attested_retirement_report.pb.go b/core/services/llo/attested_retirement_report.pb.go
index b59f623e984..d093a8eda25 100644
--- a/core/services/llo/attested_retirement_report.pb.go
+++ b/core/services/llo/attested_retirement_report.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.35.1
-// protoc v4.25.1
+// protoc-gen-go v1.36.4
+// protoc v5.29.3
// source: attested_retirement_report.proto
package llo
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -21,13 +22,12 @@ const (
)
type AttestedRetirementReport struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
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"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *AttestedRetirementReport) Reset() {
@@ -82,12 +82,11 @@ func (x *AttestedRetirementReport) GetSigs() []*AttributedOnchainSignature {
}
type AttributedOnchainSignature struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
+ Signer uint32 `protobuf:"varint,2,opt,name=signer,proto3" json:"signer,omitempty"`
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"`
+ sizeCache protoimpl.SizeCache
}
func (x *AttributedOnchainSignature) Reset() {
@@ -136,7 +135,7 @@ func (x *AttributedOnchainSignature) GetSigner() uint32 {
var File_attested_retirement_report_proto protoreflect.FileDescriptor
-var file_attested_retirement_report_proto_rawDesc = []byte{
+var file_attested_retirement_report_proto_rawDesc = string([]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,
@@ -159,16 +158,16 @@ var file_attested_retirement_report_proto_rawDesc = []byte{
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
+ file_attested_retirement_report_proto_rawDescData []byte
)
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)
+ file_attested_retirement_report_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_attested_retirement_report_proto_rawDesc), len(file_attested_retirement_report_proto_rawDesc)))
})
return file_attested_retirement_report_proto_rawDescData
}
@@ -196,7 +195,7 @@ func file_attested_retirement_report_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_attested_retirement_report_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_attested_retirement_report_proto_rawDesc), len(file_attested_retirement_report_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -207,7 +206,6 @@ func file_attested_retirement_report_proto_init() {
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/bm/dummy_transmitter.go b/core/services/llo/bm/dummy_transmitter.go
index f62635a7953..af07423b9a5 100644
--- a/core/services/llo/bm/dummy_transmitter.go
+++ b/core/services/llo/bm/dummy_transmitter.go
@@ -8,7 +8,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
"github.com/smartcontractkit/chainlink/v2/core/services/llo/evm"
@@ -58,10 +57,10 @@ func (t *transmitter) Close() error {
func (t *transmitter) Transmit(
ctx context.Context,
- digest types.ConfigDigest,
+ digest ocr2types.ConfigDigest,
seqNr uint64,
report ocr3types.ReportWithInfo[llotypes.ReportInfo],
- sigs []types.AttributedOnchainSignature,
+ sigs []ocr2types.AttributedOnchainSignature,
) error {
lggr := t.lggr
{
diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go
index 855ac7d9940..895dbdd3819 100644
--- a/core/services/llo/data_source.go
+++ b/core/services/llo/data_source.go
@@ -92,6 +92,7 @@ func newDataSource(lggr logger.Logger, registry Registry, t Telemeter) *dataSour
// Observe looks up all streams in the registry and populates a map of stream ID => value
func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, opts llo.DSOpts) error {
now := time.Now()
+ lggr := logger.With(d.lggr, "observationTimestamp", opts.ObservationTimestamp(), "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr)
if opts.VerboseLogging() {
streamIDs := make([]streams.StreamID, 0, len(streamValues))
@@ -99,7 +100,8 @@ 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, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr)
+ lggr = logger.With(lggr, "streamIDs", streamIDs)
+ lggr.Debugw("Observing streams")
}
var wg sync.WaitGroup
@@ -110,8 +112,23 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues,
var errs []ErrObservationFailed
// oc only lives for the duration of this Observe call
- oc := NewObservationContext(d.registry, d.t)
+ oc := NewObservationContext(lggr, d.registry, d.t)
+
+ // Telemetry
+ {
+ // Size needs to accommodate the max number of telemetry events that could be generated
+ // Standard case might be about 3 bridge requests per spec and one stream<=>spec
+ // Overallocate for safety (to avoid dropping packets)
+ telemCh := d.t.MakeTelemChannel(opts, 10*len(streamValues))
+ if telemCh != nil {
+ ctx = pipeline.WithTelemetryCh(ctx, telemCh)
+ // After all Observations have returned, nothing else will be sent to the
+ // telemetry channel, so it can safely be closed
+ defer close(telemCh)
+ }
+ }
+ // Observe all streams concurrently
for _, streamID := range maps.Keys(streamValues) {
go func(streamID llotypes.StreamID) {
defer wg.Done()
@@ -138,11 +155,13 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues,
}(streamID)
}
+ // Wait for all Observations to complete
wg.Wait()
- elapsed := time.Since(now)
// Only log on errors or if VerboseLogging is turned on
if len(errs) > 0 || opts.VerboseLogging() {
+ elapsed := time.Since(now)
+
slices.Sort(successfulStreamIDs)
sort.Slice(errs, func(i, j int) bool { return errs[i].streamID < errs[j].streamID })
@@ -153,7 +172,7 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues,
failedStreamIDs[i] = e.streamID
}
- lggr := logger.With(d.lggr, "elapsed", elapsed, "nSuccessfulStreams", len(successfulStreamIDs), "nFailedStreams", len(failedStreamIDs), "successfulStreamIDs", successfulStreamIDs, "failedStreamIDs", failedStreamIDs, "errs", errStrs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr)
+ lggr = logger.With(lggr, "elapsed", elapsed, "nSuccessfulStreams", len(successfulStreamIDs), "nFailedStreams", len(failedStreamIDs), "successfulStreamIDs", successfulStreamIDs, "failedStreamIDs", failedStreamIDs, "errs", errStrs)
if opts.VerboseLogging() {
lggr = logger.With(lggr, "streamValues", streamValues)
diff --git a/core/services/llo/data_source_test.go b/core/services/llo/data_source_test.go
index 349ec70007d..df352de1efd 100644
--- a/core/services/llo/data_source_test.go
+++ b/core/services/llo/data_source_test.go
@@ -2,12 +2,15 @@ package llo
import (
"context"
+ "encoding/hex"
"errors"
"fmt"
"math"
"math/big"
+ "sort"
"sync"
"testing"
+ "time"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
@@ -26,6 +29,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
+ "github.com/smartcontractkit/chainlink/v2/core/services/llo/telem"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/streams"
)
@@ -86,10 +90,14 @@ func (m *mockOpts) OutCtx() ocr3types.OutcomeContext {
func (m *mockOpts) ConfigDigest() ocr2types.ConfigDigest {
return ocr2types.ConfigDigest{6, 5, 4}
}
+func (m *mockOpts) ObservationTimestamp() time.Time {
+ return time.Unix(1737936858, 0)
+}
type mockTelemeter struct {
mu sync.Mutex
v3PremiumLegacyPackets []v3PremiumLegacyPacket
+ ch chan interface{}
}
type v3PremiumLegacyPacket struct {
@@ -109,6 +117,11 @@ func (m *mockTelemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.
m.v3PremiumLegacyPackets = append(m.v3PremiumLegacyPackets, v3PremiumLegacyPacket{run, trrs, streamID, opts, val, err})
}
+func (m *mockTelemeter) MakeTelemChannel(opts llo.DSOpts, size int) (ch chan<- interface{}) {
+ m.ch = make(chan interface{}, size)
+ return m.ch
+}
+
func Test_DataSource(t *testing.T) {
lggr := logger.TestLogger(t)
reg := &mockRegistry{make(map[streams.StreamID]*mockPipeline)}
@@ -165,7 +178,7 @@ func Test_DataSource(t *testing.T) {
vals := makeStreamValues()
err := ds.Observe(ctx, vals, opts)
- assert.NoError(t, err)
+ require.NoError(t, err)
assert.Equal(t, llo.StreamValues{
2: llo.ToDecimal(decimal.NewFromInt(40602)),
@@ -184,7 +197,28 @@ func Test_DataSource(t *testing.T) {
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)
+ require.NoError(t, pkt.err)
+
+ telems := []interface{}{}
+ for p := range tm.ch {
+ telems = append(telems, p)
+ }
+ require.Len(t, telems, 3)
+ sort.Slice(telems, func(i, j int) bool {
+ return telems[i].(*telem.LLOObservationTelemetry).StreamId < telems[j].(*telem.LLOObservationTelemetry).StreamId
+ })
+ require.IsType(t, &telem.LLOObservationTelemetry{}, telems[0])
+ obsTelem := telems[0].(*telem.LLOObservationTelemetry)
+ assert.Equal(t, uint32(1), obsTelem.StreamId)
+ assert.Equal(t, int32(llo.LLOStreamValue_Decimal), obsTelem.StreamValueType)
+ assert.Equal(t, "00000000020885", hex.EncodeToString(obsTelem.StreamValueBinary))
+ assert.Equal(t, "2181", obsTelem.StreamValueText)
+ assert.Nil(t, obsTelem.ObservationError)
+ assert.Equal(t, int64(1737936858000000000), obsTelem.ObservationTimestamp)
+ assert.Greater(t, obsTelem.ObservationFinishedAt, int64(1737936858000000000))
+ assert.Equal(t, uint32(0), obsTelem.DonId)
+ assert.Equal(t, opts.SeqNr(), obsTelem.SeqNr)
+ assert.Equal(t, opts.ConfigDigest().Hex(), hex.EncodeToString(obsTelem.ConfigDigest))
})
t.Run("records telemetry for errors", func(t *testing.T) {
diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go
index 0c7d539427e..8d70a669ffa 100644
--- a/core/services/llo/delegate.go
+++ b/core/services/llo/delegate.go
@@ -135,7 +135,7 @@ func (d *delegate) Start(ctx context.Context) error {
case 1:
lggr = logger.With(lggr, "instanceType", "Green")
}
- ocrLogger := logger.NewOCRWrapper(NewSuppressedLogger(lggr, d.cfg.ReportingPluginConfig.VerboseLogging), d.cfg.TraceLogging, func(msg string) {
+ ocrLogger := logger.NewOCRWrapper(NewSuppressedLogger(lggr, d.cfg.TraceLogging, d.cfg.ReportingPluginConfig.VerboseLogging), d.cfg.TraceLogging, func(msg string) {
// NOTE: Some OCR loggers include a DB-persist here
// We do not DB persist errors in LLO, since they could be quite voluminous and ought to be present in logs anyway.
// This is a performance optimization
diff --git a/core/services/llo/observation_context.go b/core/services/llo/observation_context.go
index 5bf82fa5a79..ef6cf6429cd 100644
--- a/core/services/llo/observation_context.go
+++ b/core/services/llo/observation_context.go
@@ -4,10 +4,13 @@ import (
"context"
"fmt"
"sync"
+ "time"
"github.com/shopspring/decimal"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-data-streams/llo"
+ "github.com/smartcontractkit/chainlink/v2/core/services/llo/telem"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/streams"
"github.com/smartcontractkit/chainlink/v2/core/utils"
@@ -33,6 +36,7 @@ type execution struct {
}
type observationContext struct {
+ l logger.Logger
r Registry
t Telemeter
@@ -41,16 +45,17 @@ type observationContext struct {
executions map[streams.Pipeline]*execution
}
-func NewObservationContext(r Registry, t Telemeter) ObservationContext {
- return newObservationContext(r, t)
+func NewObservationContext(l logger.Logger, r Registry, t Telemeter) ObservationContext {
+ return newObservationContext(l, r, t)
}
-func newObservationContext(r Registry, t Telemeter) *observationContext {
- return &observationContext{r, t, sync.Mutex{}, make(map[streams.Pipeline]*execution)}
+func newObservationContext(l logger.Logger, r Registry, t Telemeter) *observationContext {
+ return &observationContext{l, r, t, sync.Mutex{}, make(map[streams.Pipeline]*execution)}
}
func (oc *observationContext) Observe(ctx context.Context, streamID streams.StreamID, opts llo.DSOpts) (val llo.StreamValue, err error) {
run, trrs, err := oc.run(ctx, streamID)
+ observationFinishedAt := time.Now()
if err != nil {
// FIXME: This is a hack specific for V3 telemetry, future schemas should
// use a generic stream value telemetry instead
@@ -59,25 +64,65 @@ func (oc *observationContext) Observe(ctx context.Context, streamID streams.Stre
return nil, err
}
// Extract stream value based on streamID attribute
+ found := false
for _, trr := range trrs {
if trr.Task.TaskStreamID() != nil && *trr.Task.TaskStreamID() == streamID {
val, err = resultToStreamValue(trr.Result.Value)
if err != nil {
return nil, fmt.Errorf("failed to convert result to StreamValue for streamID %d: %w", streamID, err)
}
- return val, nil
+ if trr.FinishedAt.Valid {
+ observationFinishedAt = trr.FinishedAt.Time
+ }
+ found = true
+ break
}
}
// If no streamID attribute is found in the task results, then assume the
// final output is the stream ID and return that. This is safe to do since
// the registry will never return a spec that doesn't match either by tag
// or by spec streamID.
-
- val, err = extractFinalResultAsStreamValue(trrs)
- // FIXME: This is a hack specific for V3 telemetry, future schemas should
- // use a generic stream value telemetry instead
- // https://smartcontract-it.atlassian.net/browse/MERC-6290
- oc.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, err)
+ if !found {
+ // FIXME: This is a hack specific for V3 telemetry, future schemas should
+ // use the generic stream value telemetry instead
+ // https://smartcontract-it.atlassian.net/browse/MERC-6290
+ val, err = extractFinalResultAsStreamValue(trrs)
+ oc.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, err)
+ }
+ if ch := pipeline.GetTelemetryCh(ctx); ch != nil {
+ cd := opts.ConfigDigest()
+ ot := &telem.LLOObservationTelemetry{
+ StreamId: streamID,
+ ObservationTimestamp: opts.ObservationTimestamp().UnixNano(),
+ ObservationFinishedAt: observationFinishedAt.UnixNano(),
+ SeqNr: opts.SeqNr(),
+ ConfigDigest: cd[:],
+ }
+ if err != nil {
+ ot.ObservationError = new(string)
+ *ot.ObservationError = err.Error()
+ }
+ if val != nil {
+ ot.StreamValueType = int32(val.Type())
+ b, err := val.MarshalBinary()
+ if err != nil {
+ oc.l.Errorw("failed to MarshalBinary on stream value", "error", err)
+ } else {
+ ot.StreamValueBinary = b
+ }
+ s, err := val.MarshalText()
+ if err != nil {
+ oc.l.Errorw("failed to MarshalText on stream value", "error", err)
+ } else {
+ ot.StreamValueText = string(s)
+ }
+ }
+ select {
+ case ch <- ot:
+ default:
+ oc.l.Error("telemetry channel is full, dropping observation telemetry")
+ }
+ }
return
}
diff --git a/core/services/llo/observation_context_test.go b/core/services/llo/observation_context_test.go
index fe626815603..1ad1521393c 100644
--- a/core/services/llo/observation_context_test.go
+++ b/core/services/llo/observation_context_test.go
@@ -60,7 +60,8 @@ func TestObservationContext_Observe(t *testing.T) {
ctx := tests.Context(t)
r := &mockRegistry{}
telem := &mockTelemeter{}
- oc := newObservationContext(r, telem)
+ lggr := logger.TestLogger(t)
+ oc := newObservationContext(lggr, r, telem)
opts := llo.DSOpts(nil)
missingStreamID := streams.StreamID(0)
@@ -128,7 +129,8 @@ func TestObservationContext_Observe_concurrencyStressTest(t *testing.T) {
ctx := tests.Context(t)
r := &mockRegistry{}
telem := &mockTelemeter{}
- oc := newObservationContext(r, telem)
+ lggr := logger.TestLogger(t)
+ oc := newObservationContext(lggr, r, telem)
opts := llo.DSOpts(nil)
streamID := streams.StreamID(1)
@@ -252,7 +254,7 @@ result3 -> result3_parse -> multiply3;
require.NoError(t, err)
telem := &mockTelemeter{}
- oc := newObservationContext(r, telem)
+ oc := newObservationContext(lggr, r, telem)
opts := llo.DSOpts(nil)
val, err := oc.Observe(ctx, streams.StreamID(1), opts)
@@ -337,7 +339,7 @@ result3 -> result3_parse -> multiply3;
}
telem := &mockTelemeter{}
- oc := newObservationContext(r, telem)
+ oc := newObservationContext(lggr, r, telem)
opts := llo.DSOpts(nil)
// concurrency stress test
diff --git a/core/services/llo/suppressed_logger.go b/core/services/llo/suppressed_logger.go
index 9fe6e6731e5..764e484ca9f 100644
--- a/core/services/llo/suppressed_logger.go
+++ b/core/services/llo/suppressed_logger.go
@@ -2,50 +2,52 @@ package llo
import "github.com/smartcontractkit/chainlink-common/pkg/logger"
-// Suppressed logger swallows debug/info unless the verbose flag is turned on
+// Suppressed logger swallows debug and/or info levels
// Useful for OCR to calm down its verbosity
var _ logger.Logger = &SuppressedLogger{}
-func NewSuppressedLogger(lggr logger.Logger, verbose bool) logger.Logger {
+func NewSuppressedLogger(lggr logger.Logger, debug, info bool) logger.Logger {
return &SuppressedLogger{
- Logger: lggr,
- Verbose: verbose,
+ Logger: lggr,
+ DebugLevel: debug,
+ InfoLevel: info,
}
}
type SuppressedLogger struct {
logger.Logger
- Verbose bool
+ DebugLevel bool
+ InfoLevel bool
}
func (s *SuppressedLogger) Debug(args ...interface{}) {
- if s.Verbose {
+ if s.DebugLevel {
s.Logger.Debug(args...)
}
}
func (s *SuppressedLogger) Info(args ...interface{}) {
- if s.Verbose {
+ if s.InfoLevel {
s.Logger.Info(args...)
}
}
func (s *SuppressedLogger) Debugf(format string, values ...interface{}) {
- if s.Verbose {
+ if s.DebugLevel {
s.Logger.Debugf(format, values...)
}
}
func (s *SuppressedLogger) Infof(format string, values ...interface{}) {
- if s.Verbose {
+ if s.InfoLevel {
s.Logger.Infof(format, values...)
}
}
func (s *SuppressedLogger) Debugw(msg string, keysAndValues ...interface{}) {
- if s.Verbose {
+ if s.DebugLevel {
s.Logger.Debugw(msg, keysAndValues...)
}
}
func (s *SuppressedLogger) Infow(msg string, keysAndValues ...interface{}) {
- if s.Verbose {
+ if s.InfoLevel {
s.Logger.Infow(msg, keysAndValues...)
}
}
diff --git a/core/services/llo/telem/generate.go b/core/services/llo/telem/generate.go
new file mode 100644
index 00000000000..b3f5649b498
--- /dev/null
+++ b/core/services/llo/telem/generate.go
@@ -0,0 +1,3 @@
+package telem
+
+//go:generate protoc --go_out=. --go_opt=paths=source_relative telem_streams.proto
diff --git a/core/services/llo/telem/telem_streams.pb.go b/core/services/llo/telem/telem_streams.pb.go
new file mode 100644
index 00000000000..1ea10cf35ab
--- /dev/null
+++ b/core/services/llo/telem/telem_streams.pb.go
@@ -0,0 +1,429 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.36.4
+// protoc v5.29.3
+// source: telem_streams.proto
+
+package telem
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+ unsafe "unsafe"
+)
+
+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 LLOBridgeTelemetry struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ BridgeAdapterName string `protobuf:"bytes,1,opt,name=bridge_adapter_name,json=bridgeAdapterName,proto3" json:"bridge_adapter_name,omitempty"`
+ BridgeRequestData []byte `protobuf:"bytes,2,opt,name=bridge_request_data,json=bridgeRequestData,proto3" json:"bridge_request_data,omitempty"`
+ BridgeResponseData []byte `protobuf:"bytes,3,opt,name=bridge_response_data,json=bridgeResponseData,proto3" json:"bridge_response_data,omitempty"`
+ BridgeResponseError *string `protobuf:"bytes,4,opt,name=bridge_response_error,json=bridgeResponseError,proto3,oneof" json:"bridge_response_error,omitempty"`
+ BridgeResponseStatusCode int32 `protobuf:"varint,5,opt,name=bridge_response_status_code,json=bridgeResponseStatusCode,proto3" json:"bridge_response_status_code,omitempty"`
+ RequestStartTimestamp int64 `protobuf:"varint,6,opt,name=request_start_timestamp,json=requestStartTimestamp,proto3" json:"request_start_timestamp,omitempty"`
+ RequestFinishTimestamp int64 `protobuf:"varint,7,opt,name=request_finish_timestamp,json=requestFinishTimestamp,proto3" json:"request_finish_timestamp,omitempty"`
+ LocalCacheHit bool `protobuf:"varint,8,opt,name=local_cache_hit,json=localCacheHit,proto3" json:"local_cache_hit,omitempty"`
+ SpecId int32 `protobuf:"varint,9,opt,name=spec_id,json=specId,proto3" json:"spec_id,omitempty"`
+ StreamId *uint32 `protobuf:"varint,10,opt,name=stream_id,json=streamId,proto3,oneof" json:"stream_id,omitempty"`
+ DotId string `protobuf:"bytes,11,opt,name=dot_id,json=dotId,proto3" json:"dot_id,omitempty"`
+ DonId uint32 `protobuf:"varint,12,opt,name=don_id,json=donId,proto3" json:"don_id,omitempty"`
+ SeqNr uint64 `protobuf:"varint,13,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"`
+ ConfigDigest []byte `protobuf:"bytes,14,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
+ ObservationTimestamp int64 `protobuf:"varint,15,opt,name=observation_timestamp,json=observationTimestamp,proto3" json:"observation_timestamp,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *LLOBridgeTelemetry) Reset() {
+ *x = LLOBridgeTelemetry{}
+ mi := &file_telem_streams_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *LLOBridgeTelemetry) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LLOBridgeTelemetry) ProtoMessage() {}
+
+func (x *LLOBridgeTelemetry) ProtoReflect() protoreflect.Message {
+ mi := &file_telem_streams_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 LLOBridgeTelemetry.ProtoReflect.Descriptor instead.
+func (*LLOBridgeTelemetry) Descriptor() ([]byte, []int) {
+ return file_telem_streams_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *LLOBridgeTelemetry) GetBridgeAdapterName() string {
+ if x != nil {
+ return x.BridgeAdapterName
+ }
+ return ""
+}
+
+func (x *LLOBridgeTelemetry) GetBridgeRequestData() []byte {
+ if x != nil {
+ return x.BridgeRequestData
+ }
+ return nil
+}
+
+func (x *LLOBridgeTelemetry) GetBridgeResponseData() []byte {
+ if x != nil {
+ return x.BridgeResponseData
+ }
+ return nil
+}
+
+func (x *LLOBridgeTelemetry) GetBridgeResponseError() string {
+ if x != nil && x.BridgeResponseError != nil {
+ return *x.BridgeResponseError
+ }
+ return ""
+}
+
+func (x *LLOBridgeTelemetry) GetBridgeResponseStatusCode() int32 {
+ if x != nil {
+ return x.BridgeResponseStatusCode
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetRequestStartTimestamp() int64 {
+ if x != nil {
+ return x.RequestStartTimestamp
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetRequestFinishTimestamp() int64 {
+ if x != nil {
+ return x.RequestFinishTimestamp
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetLocalCacheHit() bool {
+ if x != nil {
+ return x.LocalCacheHit
+ }
+ return false
+}
+
+func (x *LLOBridgeTelemetry) GetSpecId() int32 {
+ if x != nil {
+ return x.SpecId
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetStreamId() uint32 {
+ if x != nil && x.StreamId != nil {
+ return *x.StreamId
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetDotId() string {
+ if x != nil {
+ return x.DotId
+ }
+ return ""
+}
+
+func (x *LLOBridgeTelemetry) GetDonId() uint32 {
+ if x != nil {
+ return x.DonId
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetSeqNr() uint64 {
+ if x != nil {
+ return x.SeqNr
+ }
+ return 0
+}
+
+func (x *LLOBridgeTelemetry) GetConfigDigest() []byte {
+ if x != nil {
+ return x.ConfigDigest
+ }
+ return nil
+}
+
+func (x *LLOBridgeTelemetry) GetObservationTimestamp() int64 {
+ if x != nil {
+ return x.ObservationTimestamp
+ }
+ return 0
+}
+
+type LLOObservationTelemetry struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ StreamId uint32 `protobuf:"varint,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"`
+ StreamValueType int32 `protobuf:"varint,2,opt,name=stream_value_type,json=streamValueType,proto3" json:"stream_value_type,omitempty"`
+ StreamValueBinary []byte `protobuf:"bytes,3,opt,name=stream_value_binary,json=streamValueBinary,proto3" json:"stream_value_binary,omitempty"`
+ StreamValueText string `protobuf:"bytes,4,opt,name=stream_value_text,json=streamValueText,proto3" json:"stream_value_text,omitempty"`
+ ObservationError *string `protobuf:"bytes,5,opt,name=observation_error,json=observationError,proto3,oneof" json:"observation_error,omitempty"`
+ ObservationTimestamp int64 `protobuf:"varint,6,opt,name=observation_timestamp,json=observationTimestamp,proto3" json:"observation_timestamp,omitempty"`
+ ObservationFinishedAt int64 `protobuf:"varint,7,opt,name=observation_finished_at,json=observationFinishedAt,proto3" json:"observation_finished_at,omitempty"`
+ DonId uint32 `protobuf:"varint,8,opt,name=don_id,json=donId,proto3" json:"don_id,omitempty"`
+ SeqNr uint64 `protobuf:"varint,9,opt,name=seq_nr,json=seqNr,proto3" json:"seq_nr,omitempty"`
+ ConfigDigest []byte `protobuf:"bytes,10,opt,name=config_digest,json=configDigest,proto3" json:"config_digest,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *LLOObservationTelemetry) Reset() {
+ *x = LLOObservationTelemetry{}
+ mi := &file_telem_streams_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *LLOObservationTelemetry) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LLOObservationTelemetry) ProtoMessage() {}
+
+func (x *LLOObservationTelemetry) ProtoReflect() protoreflect.Message {
+ mi := &file_telem_streams_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 LLOObservationTelemetry.ProtoReflect.Descriptor instead.
+func (*LLOObservationTelemetry) Descriptor() ([]byte, []int) {
+ return file_telem_streams_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *LLOObservationTelemetry) GetStreamId() uint32 {
+ if x != nil {
+ return x.StreamId
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetStreamValueType() int32 {
+ if x != nil {
+ return x.StreamValueType
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetStreamValueBinary() []byte {
+ if x != nil {
+ return x.StreamValueBinary
+ }
+ return nil
+}
+
+func (x *LLOObservationTelemetry) GetStreamValueText() string {
+ if x != nil {
+ return x.StreamValueText
+ }
+ return ""
+}
+
+func (x *LLOObservationTelemetry) GetObservationError() string {
+ if x != nil && x.ObservationError != nil {
+ return *x.ObservationError
+ }
+ return ""
+}
+
+func (x *LLOObservationTelemetry) GetObservationTimestamp() int64 {
+ if x != nil {
+ return x.ObservationTimestamp
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetObservationFinishedAt() int64 {
+ if x != nil {
+ return x.ObservationFinishedAt
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetDonId() uint32 {
+ if x != nil {
+ return x.DonId
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetSeqNr() uint64 {
+ if x != nil {
+ return x.SeqNr
+ }
+ return 0
+}
+
+func (x *LLOObservationTelemetry) GetConfigDigest() []byte {
+ if x != nil {
+ return x.ConfigDigest
+ }
+ return nil
+}
+
+var File_telem_streams_proto protoreflect.FileDescriptor
+
+var file_telem_streams_proto_rawDesc = string([]byte{
+ 0x0a, 0x13, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x22, 0xba, 0x05, 0x0a,
+ 0x12, 0x4c, 0x4c, 0x4f, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x74, 0x72, 0x79, 0x12, 0x2e, 0x0a, 0x13, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, 0x64,
+ 0x61, 0x70, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x11, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x4e,
+ 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
+ 0x52, 0x11, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44,
+ 0x61, 0x74, 0x61, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x12, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x37, 0x0a, 0x15, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f,
+ 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x13, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x3d,
+ 0x0a, 0x1b, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x18, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a,
+ 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74,
+ 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15,
+ 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
+ 0x26, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x68,
+ 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43,
+ 0x61, 0x63, 0x68, 0x65, 0x48, 0x69, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x70, 0x65, 0x63, 0x5f,
+ 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x70, 0x65, 0x63, 0x49, 0x64,
+ 0x12, 0x20, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20,
+ 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x88,
+ 0x01, 0x01, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x64, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6f, 0x6e,
+ 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x6f, 0x6e, 0x49, 0x64,
+ 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x15,
+ 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6f, 0x62, 0x73,
+ 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
+ 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x22, 0xc6, 0x03, 0x0a, 0x17, 0x4c, 0x4c,
+ 0x4f, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x74, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
+ 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x73,
+ 0x74, 0x72, 0x65, 0x61, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2e,
+ 0x0a, 0x13, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x62,
+ 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x73, 0x74, 0x72,
+ 0x65, 0x61, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x2a,
+ 0x0a, 0x11, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74,
+ 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x65, 0x78, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x6f, 0x62,
+ 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x15,
+ 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6f, 0x62, 0x73,
+ 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x12, 0x36, 0x0a, 0x17, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x15, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46,
+ 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6f, 0x6e,
+ 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x6f, 0x6e, 0x49, 0x64,
+ 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x42, 0x14, 0x0a, 0x12,
+ 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x42, 0x42, 0x5a, 0x40, 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,
+ 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+})
+
+var (
+ file_telem_streams_proto_rawDescOnce sync.Once
+ file_telem_streams_proto_rawDescData []byte
+)
+
+func file_telem_streams_proto_rawDescGZIP() []byte {
+ file_telem_streams_proto_rawDescOnce.Do(func() {
+ file_telem_streams_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_telem_streams_proto_rawDesc), len(file_telem_streams_proto_rawDesc)))
+ })
+ return file_telem_streams_proto_rawDescData
+}
+
+var file_telem_streams_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_telem_streams_proto_goTypes = []any{
+ (*LLOBridgeTelemetry)(nil), // 0: telem.LLOBridgeTelemetry
+ (*LLOObservationTelemetry)(nil), // 1: telem.LLOObservationTelemetry
+}
+var file_telem_streams_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_telem_streams_proto_init() }
+func file_telem_streams_proto_init() {
+ if File_telem_streams_proto != nil {
+ return
+ }
+ file_telem_streams_proto_msgTypes[0].OneofWrappers = []any{}
+ file_telem_streams_proto_msgTypes[1].OneofWrappers = []any{}
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_telem_streams_proto_rawDesc), len(file_telem_streams_proto_rawDesc)),
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_telem_streams_proto_goTypes,
+ DependencyIndexes: file_telem_streams_proto_depIdxs,
+ MessageInfos: file_telem_streams_proto_msgTypes,
+ }.Build()
+ File_telem_streams_proto = out.File
+ file_telem_streams_proto_goTypes = nil
+ file_telem_streams_proto_depIdxs = nil
+}
diff --git a/core/services/llo/telem/telem_streams.proto b/core/services/llo/telem/telem_streams.proto
new file mode 100644
index 00000000000..1063a20ec34
--- /dev/null
+++ b/core/services/llo/telem/telem_streams.proto
@@ -0,0 +1,38 @@
+syntax = "proto3";
+
+option go_package = "github.com/smartcontractkit/chainlink/v2/core/services/llo/telem";
+
+package telem;
+
+message LLOBridgeTelemetry {
+ string bridge_adapter_name = 1;
+ bytes bridge_request_data = 2;
+ bytes bridge_response_data = 3;
+ optional string bridge_response_error = 4;
+ int32 bridge_response_status_code = 5;
+ int64 request_start_timestamp=6;
+ int64 request_finish_timestamp=7;
+ bool local_cache_hit = 8;
+
+ int32 spec_id = 9;
+ optional uint32 stream_id = 10;
+ string dot_id = 11;
+ uint32 don_id = 12;
+ uint64 seq_nr = 13;
+ bytes config_digest = 14;
+
+ int64 observation_timestamp = 15;
+}
+
+message LLOObservationTelemetry {
+ uint32 stream_id = 1;
+ int32 stream_value_type = 2;
+ bytes stream_value_binary = 3;
+ string stream_value_text = 4;
+ optional string observation_error = 5;
+ int64 observation_timestamp = 6;
+ int64 observation_finished_at = 7;
+ uint32 don_id = 8;
+ uint64 seq_nr = 9;
+ bytes config_digest = 10;
+}
diff --git a/core/services/llo/telemetry.go b/core/services/llo/telemetry.go
index 0b315d78d2b..e604d4027c1 100644
--- a/core/services/llo/telemetry.go
+++ b/core/services/llo/telemetry.go
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
+ "sync"
"github.com/smartcontractkit/libocr/commontypes"
"google.golang.org/protobuf/proto"
@@ -13,17 +14,19 @@ import (
"github.com/smartcontractkit/chainlink-data-streams/llo"
"github.com/smartcontractkit/chainlink/v2/core/services/llo/evm"
+ "github.com/smartcontractkit/chainlink/v2/core/services/llo/telem"
"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"
+ legacytelem "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)
+ MakeTelemChannel(opts llo.DSOpts, size int) (ch chan<- interface{})
}
type TelemeterService interface {
@@ -43,11 +46,12 @@ func newTelemeter(lggr logger.Logger, monitoringEndpoint commontypes.MonitoringE
// feed) so we need to make sure the buffer is large enough.
//
// 2000 feeds * 5s/250ms = 40_000 should hold ~5s of buffer in the worst case.
- chTelemetryObservation := make(chan TelemetryObservation, 40_000)
+ chTelemetryPipeline := make(chan *TelemetryPipeline, 40_000)
t := &telemeter{
- chTelemetryObservation: chTelemetryObservation,
- monitoringEndpoint: monitoringEndpoint,
- donID: donID,
+ chTelemetryPipeline: chTelemetryPipeline,
+ monitoringEndpoint: monitoringEndpoint,
+ donID: donID,
+ chch: make(chan telemetryCollectionContext, 1000), // chch should be consumed from very quickly so we don't need a large buffer, but it also won't hurt
}
t.Service, t.eng = services.Config{
Name: "LLOTelemeterService",
@@ -61,16 +65,17 @@ type telemeter struct {
services.Service
eng *services.Engine
- monitoringEndpoint commontypes.MonitoringEndpoint
- chTelemetryObservation chan TelemetryObservation
- donID uint32
+ monitoringEndpoint commontypes.MonitoringEndpoint
+ chTelemetryPipeline chan *TelemetryPipeline
+ donID uint32
+ chch chan telemetryCollectionContext
}
func (t *telemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.TaskRunResults, streamID uint32, opts llo.DSOpts, val llo.StreamValue, err error) {
if t.Service.Ready() != nil {
// This should never happen, telemeter should always be started BEFORE
// the oracle and closed AFTER it
- t.eng.SugaredLogger.Errorw("Telemeter not ready, dropping observation", "run", run, "streamID", streamID, "opts", opts, "val", val, "err", err)
+ t.eng.Errorw("Telemeter not ready, dropping observation", "run", run, "streamID", streamID, "opts", opts, "val", val, "err", err)
return
}
var adapterError *eautils.AdapterError
@@ -81,20 +86,70 @@ func (t *telemeter) EnqueueV3PremiumLegacy(run *pipeline.Run, trrs pipeline.Task
// ignore errors
return
}
- tObs := TelemetryObservation{run, trrs, streamID, opts, val, dpInvariantViolationDetected}
+ tp := &TelemetryPipeline{run, trrs, streamID, opts, val, dpInvariantViolationDetected}
select {
- case t.chTelemetryObservation <- tObs:
+ case t.chTelemetryPipeline <- tp:
default:
}
}
+type telemetryCollectionContext struct {
+ in <-chan interface{}
+ opts llo.DSOpts
+}
+
+// CollectTelemetryObserve reads telem packets from the returned channel and
+// sends them to the monitoring endpoint. Stops reading when channel closed or
+// when telemeter is stopped
+//
+// CALLER IS RESPONSIBLE FOR CLOSING THE RETURNED CHANNEL TO AVOID MEMORY
+// LEAKS.
+func (t *telemeter) MakeTelemChannel(opts llo.DSOpts, size int) chan<- interface{} {
+ ch := make(chan interface{}, size)
+ tcc := telemetryCollectionContext{
+ in: ch,
+ opts: opts,
+ }
+
+ select {
+ case t.chch <- tcc:
+ default:
+ // This should be performant enough with buffer of t.chch large enough
+ // that we never hit this case, however, we should NEVER block
+ // observations on telemetry even if something pathological happens.
+ t.eng.Errorw("Telemeter chch full, will not record telemetry", "seqNr", opts.SeqNr())
+ return nil
+ }
+ return ch
+}
+
func (t *telemeter) start(_ context.Context) error {
t.eng.Go(func(ctx context.Context) {
+ wg := sync.WaitGroup{}
for {
select {
- case tObs := <-t.chTelemetryObservation:
- t.collectV3PremiumLegacyTelemetry(tObs)
+ case tcc := <-t.chch:
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for {
+ select {
+ case p, ok := <-tcc.in:
+ if !ok {
+ // channel closed by producer
+ return
+ }
+ t.collectTelemetry(p, tcc.opts)
+ case <-ctx.Done():
+ return
+ }
+ }
+ }()
+
+ case p := <-t.chTelemetryPipeline:
+ t.collectV3PremiumLegacyTelemetry(p)
case <-ctx.Done():
+ wg.Wait()
return
}
}
@@ -102,7 +157,45 @@ func (t *telemeter) start(_ context.Context) error {
return nil
}
-func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) {
+func (t *telemeter) collectTelemetry(p interface{}, opts llo.DSOpts) {
+ var msg proto.Message
+ switch v := p.(type) {
+ case *pipeline.BridgeTelemetry:
+ cd := opts.ConfigDigest()
+ msg = &telem.LLOBridgeTelemetry{
+ BridgeAdapterName: v.Name,
+ BridgeRequestData: v.RequestData,
+ BridgeResponseData: v.ResponseData,
+ BridgeResponseError: v.ResponseError,
+ BridgeResponseStatusCode: int32(v.ResponseStatusCode), //nolint:gosec // G115 // even if overflow does happen, its harmless
+ RequestStartTimestamp: v.RequestStartTimestamp.UnixNano(),
+ RequestFinishTimestamp: v.RequestFinishTimestamp.UnixNano(),
+ LocalCacheHit: v.LocalCacheHit,
+ SpecId: v.SpecID,
+ StreamId: v.StreamID,
+ DotId: v.DotID,
+ DonId: t.donID,
+ SeqNr: opts.SeqNr(),
+ ConfigDigest: cd[:],
+ ObservationTimestamp: opts.ObservationTimestamp().UnixNano(),
+ }
+ case *telem.LLOObservationTelemetry:
+ v.DonId = t.donID
+ msg = v
+ default:
+ t.eng.Warnw("Unknown telemetry type", "type", fmt.Sprintf("%T", p))
+ return
+ }
+ bytes, err := proto.Marshal(msg)
+ if err != nil {
+ t.eng.Warnf("protobuf marshal failed %v", err.Error())
+ return
+ }
+
+ t.monitoringEndpoint.SendLog(bytes)
+}
+
+func (t *telemeter) collectV3PremiumLegacyTelemetry(d *TelemetryPipeline) {
eaTelemetryValues := ocrcommon.ParseMercuryEATelemetry(t.eng.SugaredLogger, d.trrs, mercuryutils.REPORT_V3)
for _, eaTelem := range eaTelemetryValues {
var benchmarkPrice, bidPrice, askPrice int64
@@ -119,7 +212,7 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) {
askPrice = v.Ask.IntPart()
ask = v.Ask.String()
}
- tea := &telem.EnhancedEAMercury{
+ tea := &legacytelem.EnhancedEAMercury{
DataSource: eaTelem.DataSource,
DpBenchmarkPrice: eaTelem.DpBenchmarkPrice,
DpBid: eaTelem.DpBid,
@@ -147,7 +240,7 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) {
}
epoch, round, err := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr)
if err != nil {
- t.eng.SugaredLogger.Warnw("Failed to convert sequence number to epoch and round", "err", err)
+ t.eng.Warnw("Failed to convert sequence number to epoch and round", "err", err)
} else {
tea.Round = int64(round)
tea.Epoch = int64(epoch)
@@ -155,7 +248,7 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) {
bytes, err := proto.Marshal(tea)
if err != nil {
- t.eng.SugaredLogger.Warnf("protobuf marshal failed %v", err.Error())
+ t.eng.Warnf("protobuf marshal failed %v", err.Error())
continue
}
@@ -163,7 +256,12 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) {
}
}
-type TelemetryObservation struct {
+type TelemetryObserve struct {
+ Opts llo.DSOpts
+ Telemetry interface{}
+}
+
+type TelemetryPipeline struct {
run *pipeline.Run
trrs pipeline.TaskRunResults
streamID uint32
@@ -178,6 +276,9 @@ 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) MakeTelemChannel(opts llo.DSOpts, size int) (ch chan<- interface{}) {
+ return nil
+}
func (t *nullTelemeter) Start(context.Context) error {
return nil
}
diff --git a/core/services/llo/telemetry_test.go b/core/services/llo/telemetry_test.go
index ec650bedb83..1ae78a2e0fa 100644
--- a/core/services/llo/telemetry_test.go
+++ b/core/services/llo/telemetry_test.go
@@ -1,6 +1,7 @@
package llo
import (
+ "encoding/hex"
"errors"
"testing"
"time"
@@ -9,15 +10,18 @@ import (
"github.com/smartcontractkit/libocr/commontypes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "go.uber.org/zap/zapcore"
"google.golang.org/protobuf/proto"
"gopkg.in/guregu/null.v4"
"github.com/smartcontractkit/chainlink-data-streams/llo"
+ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/v2/core/services/llo/telem"
"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"
+ legacytelem "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/services/servicetest"
)
@@ -106,8 +110,8 @@ var trrs = pipeline.TaskRunResults{
},
}
-func Test_Telemeter(t *testing.T) {
- lggr := logger.Test(t)
+func Test_Telemeter_v3PremiumLegacy(t *testing.T) {
+ lggr := logger.TestLogger(t)
m := &mockMonitoringEndpoint{}
run := &pipeline.Run{ID: 42}
@@ -132,7 +136,7 @@ func Test_Telemeter(t *testing.T) {
var i int
for log := range m.chLogs {
- decoded := &telem.EnhancedEAMercury{}
+ decoded := &legacytelem.EnhancedEAMercury{}
require.NoError(t, proto.Unmarshal(log, decoded))
assert.True(t, decoded.DpInvariantViolationDetected)
if i == 2 {
@@ -150,10 +154,10 @@ func Test_Telemeter(t *testing.T) {
var i int
for log := range m.chLogs {
- decoded := &telem.EnhancedEAMercury{}
+ decoded := &legacytelem.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.InDelta(t, float64(123456.123456789), decoded.DpBenchmarkPrice, 0.0000000001)
assert.Zero(t, decoded.DpBid)
assert.Zero(t, decoded.DpAsk)
assert.False(t, decoded.DpInvariantViolationDetected)
@@ -200,7 +204,7 @@ func Test_Telemeter(t *testing.T) {
var i int
for log := range m.chLogs {
- decoded := &telem.EnhancedEAMercury{}
+ decoded := &legacytelem.EnhancedEAMercury{}
require.NoError(t, proto.Unmarshal(log, decoded))
assert.Equal(t, int64(103), decoded.ObservationBenchmarkPrice)
assert.Equal(t, "103.32", decoded.ObservationBenchmarkPriceString)
@@ -216,3 +220,107 @@ func Test_Telemeter(t *testing.T) {
}
})
}
+
+func Test_Telemeter_observationTelemetry(t *testing.T) {
+ lggr := logger.TestLogger(t)
+
+ donID := uint32(1)
+
+ opts := &mockOpts{}
+
+ t.Run("transmits *pipeline.BridgeTelemetry", func(t *testing.T) {
+ t.Parallel()
+ m := &mockMonitoringEndpoint{chLogs: make(chan []byte, 100)}
+ tm := newTelemeter(lggr, m, donID)
+ servicetest.Run(t, tm)
+ ch := tm.MakeTelemChannel(opts, 100)
+
+ ch <- &pipeline.BridgeTelemetry{
+ Name: "test-bridge-1",
+ RequestData: []byte(`foo`),
+ ResponseData: []byte(`bar`),
+ ResponseError: ptr("test error"),
+ ResponseStatusCode: 200,
+ RequestStartTimestamp: time.Unix(1, 1),
+ RequestFinishTimestamp: time.Unix(2, 1),
+ LocalCacheHit: true,
+ SpecID: 3,
+ StreamID: ptr(uint32(135)),
+ DotID: "ds1",
+ }
+
+ log := <-m.chLogs
+ decoded := &telem.LLOBridgeTelemetry{}
+ require.NoError(t, proto.Unmarshal(log, decoded))
+ assert.Equal(t, "test-bridge-1", decoded.BridgeAdapterName)
+ assert.Equal(t, []byte(`foo`), decoded.BridgeRequestData)
+ assert.Equal(t, []byte(`bar`), decoded.BridgeResponseData)
+ require.NotNil(t, decoded.BridgeResponseError)
+ assert.Equal(t, "test error", *decoded.BridgeResponseError)
+ assert.Equal(t, int32(200), decoded.BridgeResponseStatusCode)
+ assert.Equal(t, int64(1000000001), decoded.RequestStartTimestamp)
+ assert.Equal(t, int64(2000000001), decoded.RequestFinishTimestamp)
+ assert.True(t, decoded.LocalCacheHit)
+ assert.Equal(t, int32(3), decoded.SpecId)
+ require.NotNil(t, decoded.StreamId)
+ assert.Equal(t, uint32(135), *decoded.StreamId)
+ assert.Equal(t, "ds1", decoded.DotId)
+
+ // added by telemeter
+ assert.Equal(t, donID, decoded.DonId)
+ assert.Equal(t, opts.SeqNr(), decoded.SeqNr)
+ assert.Equal(t, opts.ConfigDigest().Hex(), hex.EncodeToString(decoded.ConfigDigest))
+ assert.Equal(t, opts.ObservationTimestamp().UnixNano(), decoded.ObservationTimestamp)
+ })
+ t.Run("transmits *telem.LLOObservationTelemetry", func(t *testing.T) {
+ t.Parallel()
+ m := &mockMonitoringEndpoint{chLogs: make(chan []byte, 100)}
+ tm := newTelemeter(lggr, m, donID)
+ servicetest.Run(t, tm)
+ ch := tm.MakeTelemChannel(opts, 100)
+
+ ch <- &telem.LLOObservationTelemetry{
+ StreamId: 135,
+ StreamValueType: 1,
+ StreamValueBinary: []byte{0x01, 0x02, 0x03},
+ StreamValueText: "stream value text",
+ ObservationError: ptr("test error"),
+ ObservationTimestamp: time.Unix(1, 1).UnixNano(),
+ ObservationFinishedAt: time.Unix(2, 1).UnixNano(),
+ SeqNr: 42,
+ ConfigDigest: []byte{0x01, 0x02, 0x03},
+ }
+
+ log := <-m.chLogs
+ decoded := &telem.LLOObservationTelemetry{}
+ require.NoError(t, proto.Unmarshal(log, decoded))
+ assert.Equal(t, uint32(135), decoded.StreamId)
+ assert.Equal(t, int32(1), decoded.StreamValueType)
+ assert.Equal(t, []byte{0x01, 0x02, 0x03}, decoded.StreamValueBinary)
+ assert.Equal(t, "stream value text", decoded.StreamValueText)
+ require.NotNil(t, decoded.ObservationError)
+ assert.Equal(t, "test error", *decoded.ObservationError)
+ assert.Equal(t, int64(1000000001), decoded.ObservationTimestamp)
+ assert.Equal(t, int64(2000000001), decoded.ObservationFinishedAt)
+ assert.Equal(t, uint64(42), decoded.SeqNr)
+ assert.Equal(t, []byte{0x01, 0x02, 0x03}, decoded.ConfigDigest)
+
+ // telemeter adds don ID
+ assert.Equal(t, donID, decoded.DonId)
+ })
+
+ t.Run("ignores unknown telemetry type", func(t *testing.T) {
+ t.Parallel()
+ m := &mockMonitoringEndpoint{chLogs: make(chan []byte, 100)}
+ obsLggr, observedLogs := logger.TestLoggerObserved(t, zapcore.WarnLevel)
+ tm := newTelemeter(obsLggr, m, donID)
+ servicetest.Run(t, tm)
+ ch := tm.MakeTelemChannel(opts, 100)
+
+ ch <- struct{}{}
+
+ testutils.WaitForLogMessage(t, observedLogs, "Unknown telemetry type")
+ })
+}
+
+func ptr[T any](t T) *T { return &t }
diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go
index f4d92ca079e..f6657557929 100644
--- a/core/services/ocr2/delegate.go
+++ b/core/services/ocr2/delegate.go
@@ -885,7 +885,7 @@ func (d *Delegate) newServicesMercury(
lc.ContractConfigTrackerPollInterval = 1 * time.Second // This is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520
// Disable OCR debug+info logging for legacy mercury jobs unless tracelogging is enabled, because its simply too verbose (150 jobs => ~50k logs per second)
- ocrLogger := ocrcommon.NewOCRWrapper(llo.NewSuppressedLogger(lggr, d.cfg.OCR2().TraceLogging()), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) {
+ ocrLogger := ocrcommon.NewOCRWrapper(llo.NewSuppressedLogger(lggr, d.cfg.OCR2().TraceLogging(), d.cfg.OCR2().TraceLogging()), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) {
lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error")
})
@@ -946,7 +946,6 @@ func (d *Delegate) newServicesLLO(
ocrDB *db,
lc ocrtypes.LocalConfig,
) ([]job.ServiceCtx, error) {
- lggr = logger.Sugared(lggr.Named("LLO"))
spec := jb.OCR2OracleSpec
transmitterID := spec.TransmitterID.String
if len(transmitterID) != 64 {
@@ -985,6 +984,7 @@ func (d *Delegate) newServicesLLO(
if err = json.Unmarshal(spec.PluginConfig.Bytes(), &pluginCfg); err != nil {
return nil, err
}
+ lggr = logger.Sugared(lggr.Named("LLO").With("donID", pluginCfg.DonID, "channelDefinitionsContractAddress", pluginCfg.ChannelDefinitionsContractAddress))
// Handle key bundle IDs explicitly specified in job spec
kbm := make(map[llotypes.ReportFormat]llo.Key)
diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go
index e55429d45cf..f98db3913dc 100644
--- a/core/services/ocr2/delegate_test.go
+++ b/core/services/ocr2/delegate_test.go
@@ -47,7 +47,7 @@ func TestGetEVMEffectiveTransmitterID(t *testing.T) {
txManager := txmmocks.NewMockEvmTxManager(t)
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
- GeneralConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
FeatureConfig: config.Feature(),
ListenerConfig: config.Database().Listener(),
diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go
index 985901c7b9f..22a87bc47e3 100644
--- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go
+++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go
@@ -42,8 +42,8 @@ import (
"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"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
"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"
diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go
index fde3f5e41c9..881b1199bb8 100644
--- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go
+++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go
@@ -444,7 +444,7 @@ func setupNodeCCIP(
mailMon := mailbox.NewMonitor("CCIP", lggr.Named("Mailbox"))
evmOpts := chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
ListenerConfig: config.Database().Listener(),
FeatureConfig: config.Feature(),
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 6ffd3b727fe..99caaa6f5da 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
@@ -40,9 +40,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
"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"
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 6747d5bc1e7..5c556935a69 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
@@ -444,7 +444,7 @@ func setupNodeCCIP(
mailMon := mailbox.NewMonitor("CCIP", lggr.Named("Mailbox"))
evmOpts := chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: config,
+ ChainConfigs: config.EVMConfigs(),
DatabaseConfig: config.Database(),
ListenerConfig: config.Database().Listener(),
FeatureConfig: config.Feature(),
diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go
index a575b66613d..3b6abcf2f5b 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer_test.go
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
- types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+ autotypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
@@ -50,33 +50,33 @@ func TestLogRecoverer_GetRecoverables(t *testing.T) {
{
"happy flow",
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
false,
},
{
"rate limiting",
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "3", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "4", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "5", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "6", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "3", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "4", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "5", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "6", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "3", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "4", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "5", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "3", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "4", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "5", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
false,
},
@@ -121,9 +121,9 @@ func TestLogRecoverer_Clean(t *testing.T) {
{
"clean expired",
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
- {WorkID: "3", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "3")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
+ {WorkID: "3", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "3")},
},
map[string]visitedRecord{
"1": visitedRecord{time.Now(), ocr2keepers.UpkeepPayload{
@@ -164,9 +164,9 @@ func TestLogRecoverer_Clean(t *testing.T) {
ocr2keepers.UnknownState,
},
[]ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
- {WorkID: "4", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "4")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
+ {WorkID: "4", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "4")},
},
[]string{"1", "2", "4"},
},
@@ -583,7 +583,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a filter is not found for the upkeep ID, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
},
skipFilter: true,
expectErr: true,
@@ -592,7 +592,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if an error is encountered fetching the latest block, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 0,
@@ -615,7 +615,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if an error is encountered fetching the tx receipt, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 0,
@@ -643,7 +643,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if the tx block is nil, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 0,
@@ -671,7 +671,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log trigger extension block number is 0, and the block number on the tx receipt is not recoverable, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 0,
@@ -701,7 +701,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is not recoverable, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 200,
@@ -731,7 +731,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block has does not match, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 200,
@@ -763,7 +763,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is recoverable, when the upkeep state reader errors, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 80,
@@ -798,7 +798,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is recoverable, when the upkeep state reader returns a non recoverable state, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 80,
@@ -835,7 +835,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is recoverable, when the filter address is empty, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 80,
@@ -875,7 +875,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is recoverable, when the log poller returns an error fetching logs, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 80,
@@ -910,7 +910,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "if a log block is recoverable, when logs cannot be found for an upkeep ID, an error is returned",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: ocr2keepers.Trigger{
LogTriggerExtension: &ocr2keepers.LogTriggerExtension{
BlockNumber: 80,
@@ -949,7 +949,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "happy path with empty check data",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: func() ocr2keepers.Trigger {
t := ocr2keepers.NewTrigger(
ocr2keepers.BlockNumber(80),
@@ -1000,7 +1000,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
{
name: "happy path with check data",
proposal: ocr2keepers.CoordinatedBlockProposal{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "123"),
+ UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123"),
Trigger: func() ocr2keepers.Trigger {
t := ocr2keepers.NewTrigger(
ocr2keepers.BlockNumber(80),
@@ -1061,7 +1061,7 @@ func TestLogRecoverer_GetProposalData(t *testing.T) {
filterStore.AddActiveUpkeeps(upkeepFilter{
addr: []byte("test"),
topics: []common.Hash{common.HexToHash("0x1"), common.HexToHash("0x2"), common.HexToHash("0x3"), common.HexToHash("0x4")},
- upkeepID: core.GenUpkeepID(types2.LogTrigger, "123").BigInt(),
+ upkeepID: core.GenUpkeepID(autotypes.LogTrigger, "123").BigInt(),
})
}
@@ -1111,34 +1111,34 @@ func TestLogRecoverer_pending(t *testing.T) {
name: "add new and existing",
maxPerUpkeep: 10,
exist: []ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
},
new: []ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
errored: []bool{false, false},
want: []ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "2")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "2")},
},
},
{
name: "exceed limits for upkeep",
maxPerUpkeep: 3,
exist: []ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "3", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "3", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
},
new: []ocr2keepers.UpkeepPayload{
- {WorkID: "4", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
+ {WorkID: "4", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
},
errored: []bool{true},
want: []ocr2keepers.UpkeepPayload{
- {WorkID: "1", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "2", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
- {WorkID: "3", UpkeepID: core.GenUpkeepID(types2.LogTrigger, "1")},
+ {WorkID: "1", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "2", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
+ {WorkID: "3", UpkeepID: core.GenUpkeepID(autotypes.LogTrigger, "1")},
},
},
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder_test.go
index 7cd63dd308a..d5837488ff4 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/payload_builder_test.go
@@ -5,12 +5,11 @@ import (
"math/big"
"testing"
- types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
-
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
- types "github.com/smartcontractkit/chainlink-common/pkg/types/automation"
+ "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+ "github.com/smartcontractkit/chainlink-common/pkg/types/automation"
"github.com/smartcontractkit/chainlink/v2/core/internal/testutils"
"github.com/smartcontractkit/chainlink/v2/core/logger"
@@ -23,8 +22,8 @@ func TestNewPayloadBuilder(t *testing.T) {
name string
activeList ActiveUpkeepList
recoverer logprovider.LogRecoverer
- proposals []types.CoordinatedBlockProposal
- wantPayloads []types.UpkeepPayload
+ proposals []automation.CoordinatedBlockProposal
+ wantPayloads []automation.UpkeepPayload
}{
{
name: "for log trigger upkeeps, new payloads are created",
@@ -33,43 +32,43 @@ func TestNewPayloadBuilder(t *testing.T) {
return true
},
},
- proposals: []types.CoordinatedBlockProposal{
+ proposals: []automation.CoordinatedBlockProposal{
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "abc"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "abc"),
WorkID: "workID1",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
},
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "def"),
WorkID: "workID2",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 2,
BlockHash: [32]byte{2},
},
},
},
recoverer: &mockLogRecoverer{
- GetProposalDataFn: func(ctx context.Context, proposal types.CoordinatedBlockProposal) ([]byte, error) {
+ GetProposalDataFn: func(ctx context.Context, proposal automation.CoordinatedBlockProposal) ([]byte, error) {
return []byte{1, 2, 3}, nil
},
},
- wantPayloads: []types.UpkeepPayload{
+ wantPayloads: []automation.UpkeepPayload{
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "abc"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "abc"),
WorkID: "714f83255c5b562823725748c4a75777c9b78ea8c5ba72ea819926a1fecd389e",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
CheckData: []byte{1, 2, 3},
},
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "def"),
WorkID: "3956daa0378d6a761fe972ee00fe98338f17fb6b7865c1d49a8a416cd85977b8",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 2,
BlockHash: [32]byte{2},
},
@@ -81,54 +80,54 @@ func TestNewPayloadBuilder(t *testing.T) {
name: "for an inactive log trigger upkeep, an empty payload is added to the list of payloads",
activeList: &mockActiveUpkeepList{
IsActiveFn: func(id *big.Int) bool {
- return core.GenUpkeepID(types2.LogTrigger, "ghi").BigInt().Cmp(id) != 0
+ return core.GenUpkeepID(types.LogTrigger, "ghi").BigInt().Cmp(id) != 0
},
},
- proposals: []types.CoordinatedBlockProposal{
+ proposals: []automation.CoordinatedBlockProposal{
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "abc"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "abc"),
WorkID: "workID1",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
},
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "def"),
WorkID: "workID2",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 2,
BlockHash: [32]byte{2},
},
},
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "ghi"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "ghi"),
WorkID: "workID3",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 3,
BlockHash: [32]byte{3},
},
},
},
recoverer: &mockLogRecoverer{
- GetProposalDataFn: func(ctx context.Context, proposal types.CoordinatedBlockProposal) ([]byte, error) {
+ GetProposalDataFn: func(ctx context.Context, proposal automation.CoordinatedBlockProposal) ([]byte, error) {
return []byte{1, 2, 3}, nil
},
},
- wantPayloads: []types.UpkeepPayload{
+ wantPayloads: []automation.UpkeepPayload{
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "abc"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "abc"),
WorkID: "714f83255c5b562823725748c4a75777c9b78ea8c5ba72ea819926a1fecd389e",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
CheckData: []byte{1, 2, 3},
},
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "def"),
WorkID: "3956daa0378d6a761fe972ee00fe98338f17fb6b7865c1d49a8a416cd85977b8",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 2,
BlockHash: [32]byte{2},
},
@@ -144,22 +143,22 @@ func TestNewPayloadBuilder(t *testing.T) {
return true
},
},
- proposals: []types.CoordinatedBlockProposal{
+ proposals: []automation.CoordinatedBlockProposal{
{
- UpkeepID: core.GenUpkeepID(types2.LogTrigger, "abc"),
+ UpkeepID: core.GenUpkeepID(types.LogTrigger, "abc"),
WorkID: "workID1",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
},
},
recoverer: &mockLogRecoverer{
- GetProposalDataFn: func(ctx context.Context, proposal types.CoordinatedBlockProposal) ([]byte, error) {
+ GetProposalDataFn: func(ctx context.Context, proposal automation.CoordinatedBlockProposal) ([]byte, error) {
return nil, errors.New("recoverer boom")
},
},
- wantPayloads: []types.UpkeepPayload{
+ wantPayloads: []automation.UpkeepPayload{
{},
},
},
@@ -170,21 +169,21 @@ func TestNewPayloadBuilder(t *testing.T) {
return true
},
},
- proposals: []types.CoordinatedBlockProposal{
+ proposals: []automation.CoordinatedBlockProposal{
{
- UpkeepID: core.GenUpkeepID(types2.ConditionTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.ConditionTrigger, "def"),
WorkID: "workID1",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
},
},
- wantPayloads: []types.UpkeepPayload{
+ wantPayloads: []automation.UpkeepPayload{
{
- UpkeepID: core.GenUpkeepID(types2.ConditionTrigger, "def"),
+ UpkeepID: core.GenUpkeepID(types.ConditionTrigger, "def"),
WorkID: "58f2f231792448679a75bac6efc2af4ba731901f0cb93a44a366525751cbabfb",
- Trigger: types.Trigger{
+ Trigger: automation.Trigger{
BlockNumber: 1,
BlockHash: [32]byte{1},
},
@@ -204,9 +203,9 @@ func TestNewPayloadBuilder(t *testing.T) {
type mockLogRecoverer struct {
logprovider.LogRecoverer
- GetProposalDataFn func(context.Context, types.CoordinatedBlockProposal) ([]byte, error)
+ GetProposalDataFn func(context.Context, automation.CoordinatedBlockProposal) ([]byte, error)
}
-func (r *mockLogRecoverer) GetProposalData(ctx context.Context, p types.CoordinatedBlockProposal) ([]byte, error) {
+func (r *mockLogRecoverer) GetProposalData(ctx context.Context, p automation.CoordinatedBlockProposal) ([]byte, error) {
return r.GetProposalDataFn(ctx, p)
}
diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go
index d73338abea9..e30bcfcd30d 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go
@@ -23,7 +23,7 @@ import (
"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"
+ autotypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller"
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
@@ -300,7 +300,7 @@ func (r *EvmRegistry) refreshActiveUpkeeps(ctx context.Context) error {
continue
}
switch core.GetUpkeepType(*uid) {
- case types2.LogTrigger:
+ case autotypes.LogTrigger:
logTriggerIDs = append(logTriggerIDs, id)
default:
}
@@ -522,7 +522,7 @@ func (r *EvmRegistry) removeFromActive(ctx context.Context, id *big.Int) {
uid.FromBigInt(id)
trigger := core.GetUpkeepType(*uid)
switch trigger {
- case types2.LogTrigger:
+ case autotypes.LogTrigger:
if err := r.logEventProvider.UnregisterFilter(ctx, id); err != nil {
r.lggr.Warnw("failed to unregister log filter", "upkeepID", id.String())
}
@@ -590,7 +590,7 @@ func (r *EvmRegistry) updateTriggerConfig(ctx context.Context, id *big.Int, cfg
uid := &ocr2keepers.UpkeepIdentifier{}
uid.FromBigInt(id)
switch core.GetUpkeepType(*uid) {
- case types2.LogTrigger:
+ case autotypes.LogTrigger:
if len(cfg) == 0 {
fetched, err := r.fetchTriggerConfig(ctx, id)
if err != nil {
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 da2587a74ef..9096ca26e16 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
@@ -16,12 +16,11 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ autotypes "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- types2 "github.com/smartcontractkit/chainlink-common/pkg/types"
+ commontypes "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"
-
"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/gethwrappers/generated/streams_lookup_compatible_interface"
@@ -378,9 +377,9 @@ func TestRegistry_VerifyLogExists(t *testing.T) {
func TestRegistry_CheckUpkeeps(t *testing.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")
+ uid0 := core.GenUpkeepID(autotypes.UpkeepType(0), "p0")
+ uid1 := core.GenUpkeepID(autotypes.UpkeepType(1), "p1")
+ uid2 := core.GenUpkeepID(autotypes.UpkeepType(1), "p2")
extension1 := &ocr2keepers.LogTriggerExtension{
TxHash: common.HexToHash("0xc8def8abdcf3a4eaaf6cc13bff3e4e2a7168d86ea41dbbf97451235aa76c3651"),
@@ -538,9 +537,9 @@ func TestRegistry_CheckUpkeeps(t *testing.T) {
}
func TestRegistry_SimulatePerformUpkeeps(t *testing.T) {
- uid0 := core.GenUpkeepID(types3.UpkeepType(0), "p0")
- uid1 := core.GenUpkeepID(types3.UpkeepType(1), "p1")
- uid2 := core.GenUpkeepID(types3.UpkeepType(1), "p2")
+ uid0 := core.GenUpkeepID(autotypes.UpkeepType(0), "p0")
+ uid1 := core.GenUpkeepID(autotypes.UpkeepType(1), "p1")
+ uid2 := core.GenUpkeepID(autotypes.UpkeepType(1), "p2")
extension1 := &ocr2keepers.LogTriggerExtension{
TxHash: common.HexToHash("0xc8def8abdcf3a4eaaf6cc13bff3e4e2a7168d86ea41dbbf97451235aa76c3651"),
@@ -692,7 +691,7 @@ func setupEVMRegistry(t *testing.T) *EvmRegistry {
headFunc: func(ocr2keepers.BlockKey) {},
chLog: make(chan logpoller.Log, 1000),
mercury: &MercuryConfig{
- cred: &types2.MercuryCredentials{
+ cred: &commontypes.MercuryCredentials{
LegacyURL: "https://google.old.com",
URL: "https://google.com",
Username: "FakeClientID",
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 2982714ba28..76249f02351 100644
--- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go
+++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go
@@ -14,12 +14,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
- types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types"
+ autotypes "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"
- types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types"
+ evmhttypes "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"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated"
@@ -258,7 +258,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
{
name: "an error is returned when fetching indexed logs for IAutomationV21PlusCommonUpkeepUnpaused errors",
ids: []*big.Int{
- core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
},
logEventProvider: &mockLogEventProvider{
RefreshActiveUpkeepsFn: func(ctx context.Context, ids ...*big.Int) ([]*big.Int, error) {
@@ -281,8 +281,8 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
{
name: "an error is returned when fetching indexed logs for IAutomationV21PlusCommonUpkeepTriggerConfigSet errors",
ids: []*big.Int{
- core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
- core.GenUpkeepID(types2.ConditionTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.ConditionTrigger, "abc").BigInt(),
big.NewInt(-1),
},
logEventProvider: &mockLogEventProvider{
@@ -306,8 +306,8 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
{
name: "an error is returned when parsing the logs using the registry errors",
ids: []*big.Int{
- core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
- core.GenUpkeepID(types2.ConditionTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.ConditionTrigger, "abc").BigInt(),
big.NewInt(-1),
},
logEventProvider: &mockLogEventProvider{
@@ -335,8 +335,8 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
{
name: "an error is returned when registering the filter errors",
ids: []*big.Int{
- core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
- core.GenUpkeepID(types2.ConditionTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.ConditionTrigger, "abc").BigInt(),
big.NewInt(-1),
},
logEventProvider: &mockLogEventProvider{
@@ -366,11 +366,11 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
if log.BlockNumber == 1 {
return &autov2common.IAutomationV21PlusCommonUpkeepTriggerConfigSet{
TriggerConfig: []byte{1, 2, 3},
- Id: core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
}, nil
}
return &autov2common.IAutomationV21PlusCommonUpkeepUnpaused{
- Id: core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
}, nil
},
GetUpkeepTriggerConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
@@ -388,9 +388,9 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
{
name: "log trigger upkeeps are refreshed without error",
ids: []*big.Int{
- core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
- core.GenUpkeepID(types2.LogTrigger, "def").BigInt(),
- core.GenUpkeepID(types2.ConditionTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
+ core.GenUpkeepID(autotypes.LogTrigger, "def").BigInt(),
+ core.GenUpkeepID(autotypes.ConditionTrigger, "abc").BigInt(),
big.NewInt(-1),
},
logEventProvider: &mockLogEventProvider{
@@ -419,12 +419,12 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
ParseLogFn: func(log coreTypes.Log) (generated.AbigenLog, error) {
if log.BlockNumber == 1 {
return &autov2common.IAutomationV21PlusCommonUpkeepTriggerConfigSet{
- Id: core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
TriggerConfig: []byte{1, 2, 3},
}, nil
}
return &autov2common.IAutomationV21PlusCommonUpkeepUnpaused{
- Id: core.GenUpkeepID(types2.LogTrigger, "def").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "def").BigInt(),
}, nil
},
GetUpkeepTriggerConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
@@ -442,7 +442,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
ids: func() []*big.Int {
res := []*big.Int{}
for i := 0; i < logTriggerRefreshBatchSize*3; i++ {
- res = append(res, core.GenUpkeepID(types2.LogTrigger, fmt.Sprintf("%d", i)).BigInt())
+ res = append(res, core.GenUpkeepID(autotypes.LogTrigger, fmt.Sprintf("%d", i)).BigInt())
}
return res
}(),
@@ -471,12 +471,12 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
ParseLogFn: func(log coreTypes.Log) (generated.AbigenLog, error) {
if log.BlockNumber == 1 {
return &autov2common.IAutomationV21PlusCommonUpkeepTriggerConfigSet{
- Id: core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
TriggerConfig: []byte{1, 2, 3},
}, nil
}
return &autov2common.IAutomationV21PlusCommonUpkeepUnpaused{
- Id: core.GenUpkeepID(types2.LogTrigger, "def").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "def").BigInt(),
}, nil
},
GetUpkeepTriggerConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
@@ -494,7 +494,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
ids: func() []*big.Int {
res := []*big.Int{}
for i := 0; i < logTriggerRefreshBatchSize+3; i++ {
- res = append(res, core.GenUpkeepID(types2.LogTrigger, fmt.Sprintf("%d", i)).BigInt())
+ res = append(res, core.GenUpkeepID(autotypes.LogTrigger, fmt.Sprintf("%d", i)).BigInt())
}
return res
}(),
@@ -525,12 +525,12 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
ParseLogFn: func(log coreTypes.Log) (generated.AbigenLog, error) {
if log.BlockNumber == 1 {
return &autov2common.IAutomationV21PlusCommonUpkeepTriggerConfigSet{
- Id: core.GenUpkeepID(types2.LogTrigger, "abc").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "abc").BigInt(),
TriggerConfig: []byte{1, 2, 3},
}, nil
}
return &autov2common.IAutomationV21PlusCommonUpkeepUnpaused{
- Id: core.GenUpkeepID(types2.LogTrigger, "def").BigInt(),
+ Id: core.GenUpkeepID(autotypes.LogTrigger, "def").BigInt(),
}, nil
},
GetUpkeepTriggerConfigFn: func(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) {
@@ -547,7 +547,7 @@ func TestRegistry_refreshLogTriggerUpkeeps(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
ctx := tests.Context(t)
lggr := logger.Test(t)
- var hb types3.HeadBroadcaster
+ var hb evmhttypes.HeadBroadcaster
var lp logpoller.LogPoller
bs := NewBlockSubscriber(hb, lp, 1000, lggr)
diff --git a/core/services/ocr2/testhelpers/onchain_config.go b/core/services/ocr2/testhelpers/onchain_config.go
index a2cb6f91f29..9758238b27e 100644
--- a/core/services/ocr2/testhelpers/onchain_config.go
+++ b/core/services/ocr2/testhelpers/onchain_config.go
@@ -1,31 +1,12 @@
package testhelpers
import (
+ "context"
"math/big"
- "github.com/smartcontractkit/libocr/bigbigendian"
+ "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median"
)
func GenerateDefaultOCR2OnchainConfig(minValue *big.Int, maxValue *big.Int) ([]byte, error) {
- serializedConfig := make([]byte, 0)
-
- s1, err := bigbigendian.SerializeSigned(1, big.NewInt(1)) // version
- if err != nil {
- return nil, err
- }
- serializedConfig = append(serializedConfig, s1...)
-
- s2, err := bigbigendian.SerializeSigned(24, minValue) // min
- if err != nil {
- return nil, err
- }
- serializedConfig = append(serializedConfig, s2...)
-
- s3, err := bigbigendian.SerializeSigned(24, maxValue) // max
- if err != nil {
- return nil, err
- }
- serializedConfig = append(serializedConfig, s3...)
-
- return serializedConfig, nil
+ return median.StandardOnchainConfigCodec{}.Encode(context.Background(), median.OnchainConfig{Min: minValue, Max: maxValue})
}
diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go
index 3872955e5a3..50b99adf8b9 100644
--- a/core/services/ocrcommon/telemetry.go
+++ b/core/services/ocrcommon/telemetry.go
@@ -473,7 +473,6 @@ func (e *EnhancedTelemetryService[T]) collectMercuryEnhancedTelemetry(d Enhanced
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())
diff --git a/core/services/ocrcommon/transmitter.go b/core/services/ocrcommon/transmitter.go
index e3d495ddcdc..1052e7b38ad 100644
--- a/core/services/ocrcommon/transmitter.go
+++ b/core/services/ocrcommon/transmitter.go
@@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders"
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore"
- types2 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
+ evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
)
type roundRobinKeystore interface {
@@ -94,7 +94,7 @@ func NewOCR2FeedsTransmitter(
checker txmgr.TransmitCheckerSpec,
chainID *big.Int,
ks keystore.Eth,
- dualTransmissionConfig *types2.DualTransmissionConfig,
+ dualTransmissionConfig *evmtypes.DualTransmissionConfig,
) (Transmitter, error) {
// Ensure that a keystore is provided.
if ks == nil {
diff --git a/core/services/pipeline/common.go b/core/services/pipeline/common.go
index 65c47dd1cc9..a1b66ba8931 100644
--- a/core/services/pipeline/common.go
+++ b/core/services/pipeline/common.go
@@ -539,3 +539,26 @@ func selectBlock(block string) (string, error) {
}
return "", pkgerrors.Errorf("unsupported block param: %s", block)
}
+
+// WithTelemetry adds an optional telemetry channel to the context. If ch is
+// non-nil, certain tasks MAY choose to send arbitrary telemetry data on this
+// channel. The provided channel SHOULD be buffered, but if it blocks, the task
+// SHOULD NOT block.
+type contextKey string
+
+const ctxTelemetryKey contextKey = "telemetry"
+
+func WithTelemetryCh(ctx context.Context, ch chan<- interface{}) context.Context {
+ if ch == nil {
+ return ctx
+ }
+ return context.WithValue(ctx, ctxTelemetryKey, ch)
+}
+
+func GetTelemetryCh(ctx context.Context) chan<- interface{} {
+ ch, ok := ctx.Value(ctxTelemetryKey).(chan<- interface{})
+ if !ok {
+ return nil
+ }
+ return ch
+}
diff --git a/core/services/pipeline/common_http.go b/core/services/pipeline/common_http.go
index 83fa21382ea..04e20fc8568 100644
--- a/core/services/pipeline/common_http.go
+++ b/core/services/pipeline/common_http.go
@@ -24,19 +24,23 @@ func makeHTTPRequest(
requestData MapParam,
client *http.Client,
httpLimit int64,
-) ([]byte, int, http.Header, time.Duration, error) {
+) (responseBytes []byte, statusCode int, respHeaders http.Header, start, finish time.Time, err error) {
var bodyReader io.Reader
if requestData != nil {
- bodyBytes, err := json.Marshal(requestData)
+ var bodyBytes []byte
+ bodyBytes, err = json.Marshal(requestData)
if err != nil {
- return nil, 0, nil, 0, errors.Wrap(err, "failed to encode request body as JSON")
+ err = errors.Wrap(err, "failed to encode request body as JSON")
+ return
}
bodyReader = bytes.NewReader(bodyBytes)
}
- request, err := http.NewRequestWithContext(ctx, string(method), url.String(), bodyReader)
+ var request *http.Request
+ request, err = http.NewRequestWithContext(ctx, string(method), url.String(), bodyReader)
if err != nil {
- return nil, 0, nil, 0, errors.Wrap(err, "failed to create http.Request")
+ err = errors.Wrap(err, "failed to create http.Request")
+ return
}
request.Header.Set("Content-Type", "application/json")
if len(reqHeaders)%2 != 0 {
@@ -53,21 +57,22 @@ func makeHTTPRequest(
Logger: logger.Sugared(lggr).Named("HTTPRequest"),
}
- start := time.Now()
- responseBytes, statusCode, respHeaders, err := httpRequest.SendRequest()
+ start = time.Now()
+ responseBytes, statusCode, respHeaders, err = httpRequest.SendRequest()
+ finish = time.Now()
if ctx.Err() != nil {
- return nil, 0, nil, 0, errors.New("http request timed out or interrupted")
+ err = errors.New("http request timed out or interrupted")
+ return
}
if err != nil {
- return nil, 0, nil, 0, errors.Wrapf(err, "error making http request")
+ err = errors.Wrapf(err, "error making http request")
+ return
}
- elapsed := time.Since(start) // TODO: return elapsed from utils/http
if statusCode >= 400 {
- maybeErr := bestEffortExtractError(responseBytes)
- return responseBytes, statusCode, respHeaders, 0, errors.Errorf("got error from %s: (status code %v) %s", url.String(), statusCode, maybeErr)
+ err = errors.Errorf("got error from %s: (status code %v) %s", url.String(), statusCode, bestEffortExtractError(responseBytes))
}
- return responseBytes, statusCode, respHeaders, elapsed, nil
+ return
}
type PossibleErrorResponses struct {
diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go
index c9b3e1ed6ff..7b636534513 100644
--- a/core/services/pipeline/runner_test.go
+++ b/core/services/pipeline/runner_test.go
@@ -40,7 +40,7 @@ import (
func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) {
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
@@ -516,7 +516,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) {
cfg := configtest.NewTestGeneralConfig(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
@@ -562,7 +562,7 @@ func Test_PipelineRunner_ExecuteAndInsertFinishedRun_SavingTheSpec(t *testing.T)
cfg := configtest.NewTestGeneralConfig(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
@@ -1038,7 +1038,7 @@ func Test_PipelineRunner_ExecuteRun(t *testing.T) {
cfg := configtest.NewTestGeneralConfig(t)
ethKeyStore := cltest.NewKeyStore(t, db).Eth()
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/pipeline/task.bridge.go b/core/services/pipeline/task.bridge.go
index a885bee8df0..4ab6b0ac967 100644
--- a/core/services/pipeline/task.bridge.go
+++ b/core/services/pipeline/task.bridge.go
@@ -72,6 +72,20 @@ type BridgeTask struct {
httpClient *http.Client
}
+type BridgeTelemetry struct {
+ RequestStartTimestamp time.Time `json:"requestStartTimestamp"`
+ RequestFinishTimestamp time.Time `json:"requestFinishTimestamp"`
+ RequestData []byte `json:"requestData"`
+ ResponseData []byte `json:"responseData"`
+ Name string `json:"name"`
+ DotID string `json:"dotID"`
+ ResponseError *string `json:"responseError"`
+ StreamID *uint32 `json:"streamID"`
+ SpecID int32 `json:"specID"`
+ ResponseStatusCode int `json:"responseStatusCode"`
+ LocalCacheHit bool `json:"localCacheHit"`
+}
+
var _ Task = (*BridgeTask)(nil)
var zeroURL = new(url.URL)
@@ -171,7 +185,37 @@ func (t *BridgeTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, inp
}
var cachedResponse bool
- responseBytes, statusCode, headers, elapsed, err := makeHTTPRequest(requestCtx, lggr, "POST", url, reqHeaders, requestData, t.httpClient, t.config.DefaultHTTPLimit())
+ responseBytes, statusCode, headers, start, finish, err := makeHTTPRequest(requestCtx, lggr, "POST", url, reqHeaders, requestData, t.httpClient, t.config.DefaultHTTPLimit())
+ elapsed := finish.Sub(start)
+
+ defer func() {
+ telemetryCh := GetTelemetryCh(ctx)
+ if telemetryCh != nil {
+ bt := &BridgeTelemetry{
+ Name: t.Name,
+ RequestData: requestDataJSON,
+ ResponseData: responseBytes,
+ ResponseStatusCode: statusCode,
+ RequestStartTimestamp: start,
+ RequestFinishTimestamp: finish,
+ LocalCacheHit: cachedResponse,
+ SpecID: t.specId,
+ DotID: t.DotID(),
+ }
+ if err != nil {
+ bt.ResponseError = new(string)
+ *bt.ResponseError = err.Error()
+ }
+ if t.StreamID.Valid {
+ bt.StreamID = &t.StreamID.Uint32
+ }
+ select {
+ case telemetryCh <- bt:
+ default:
+ lggr.Warn("bridge task: telemetry channel is full, dropping telemetry")
+ }
+ }
+ }()
// check for external adapter response object status
if code, ok := eautils.BestEffortExtractEAStatus(responseBytes); ok {
diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go
index cd81f8656fd..2ad0616fdd5 100644
--- a/core/services/pipeline/task.bridge_test.go
+++ b/core/services/pipeline/task.bridge_test.go
@@ -214,6 +214,8 @@ func TestBridgeTask_Happy(t *testing.T) {
db := pgtest.NewSqlxDB(t)
cfg := configtest.NewTestGeneralConfig(t)
+ telemCh := make(chan interface{}, 1)
+ ctx := pipeline.WithTelemetryCh(testutils.Context(t), telemCh)
s1 := httptest.NewServer(fakePriceResponder(t, utils.MustUnmarshalToMap(btcUSDPairing), decimal.NewFromInt(9700), "", nil))
defer s1.Close()
@@ -231,11 +233,11 @@ func TestBridgeTask_Happy(t *testing.T) {
}
c := clhttptest.NewTestLocalOnlyHTTPClient()
trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns())
- specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute))
+ specID, err := trORM.CreateSpec(ctx, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute))
require.NoError(t, err)
task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c)
- result, runInfo := task.Run(testutils.Context(t), logger.TestLogger(t), pipeline.NewVarsFrom(nil), nil)
+ result, runInfo := task.Run(ctx, logger.TestLogger(t), pipeline.NewVarsFrom(nil), nil)
assert.False(t, runInfo.IsPending)
assert.False(t, runInfo.IsRetryable)
require.NoError(t, result.Error)
@@ -248,6 +250,22 @@ func TestBridgeTask_Happy(t *testing.T) {
err = json.Unmarshal([]byte(result.Value.(string)), &x)
require.NoError(t, err)
require.Equal(t, decimal.NewFromInt(9700), x.Data.Result)
+
+ telem := <-telemCh
+ require.IsType(t, &pipeline.BridgeTelemetry{}, telem)
+ btelem := telem.(*pipeline.BridgeTelemetry)
+ assert.Equal(t, string(bridge.Name), btelem.Name)
+ assert.Equal(t, btcUSDPairing, string(btelem.RequestData))
+ assert.Equal(t, `{"errorMessage":null,"error":null,"statusCode":null,"providerStatusCode":null,"data":{"result":"9700"}}
+`, string(btelem.ResponseData))
+ assert.Nil(t, btelem.ResponseError)
+ assert.NotZero(t, btelem.RequestStartTimestamp)
+ assert.NotZero(t, btelem.RequestFinishTimestamp)
+ assert.Equal(t, 200, btelem.ResponseStatusCode)
+ assert.False(t, btelem.LocalCacheHit)
+ assert.Equal(t, specID, btelem.SpecID)
+ assert.NotEqual(t, uuid.Nil, btelem.StreamID)
+ assert.NotEqual(t, uuid.Nil, btelem.DotID)
}
func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) {
diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go
index 9e87fe5c19c..920964e5e48 100644
--- a/core/services/pipeline/task.eth_call_test.go
+++ b/core/services/pipeline/task.eth_call_test.go
@@ -314,7 +314,7 @@ func TestETHCallTask(t *testing.T) {
if test.expectedErrorCause != nil || test.expectedErrorContains != "" {
legacyChains = evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go
index e3864a41dca..0e1e96593fc 100644
--- a/core/services/pipeline/task.eth_tx_test.go
+++ b/core/services/pipeline/task.eth_tx_test.go
@@ -580,7 +580,7 @@ func TestETHTxTask(t *testing.T) {
legacyChains := evmtest.NewLegacyChains(t, evmtest.TestChainOpts{
DB: db,
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/pipeline/task.http.go b/core/services/pipeline/task.http.go
index c23b1e8fa99..7f39fd7006a 100644
--- a/core/services/pipeline/task.http.go
+++ b/core/services/pipeline/task.http.go
@@ -104,7 +104,8 @@ func (t *HTTPTask) Run(ctx context.Context, lggr logger.Logger, vars Vars, input
} else {
client = t.httpClient
}
- responseBytes, statusCode, respHeaders, elapsed, err := makeHTTPRequest(requestCtx, lggr, method, url, reqHeaders, requestData, client, t.config.DefaultHTTPLimit())
+ responseBytes, statusCode, respHeaders, start, finish, err := makeHTTPRequest(requestCtx, lggr, method, url, reqHeaders, requestData, client, t.config.DefaultHTTPLimit())
+ elapsed := finish.Sub(start).Milliseconds()
if err != nil {
if errors.Is(errors.Cause(err), clhttp.ErrDisallowedIP) {
err = errors.Wrap(err, `connections to local resources are disabled by default, if you are sure this is safe, you can enable on a per-task basis by setting allowUnrestrictedNetworkAccess="true" in the pipeline task spec, e.g. fetch [type="http" method=GET url="$(decode_cbor.url)" allowUnrestrictedNetworkAccess="true"]`)
diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go
index 18d10ca994f..91645a5ffe3 100644
--- a/core/services/relay/evm/evm.go
+++ b/core/services/relay/evm/evm.go
@@ -209,7 +209,7 @@ func NewRelayer(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain,
if err != nil {
return nil, fmt.Errorf("cannot create evm relayer: %w", err)
}
- sugared := logger.Sugared(lggr).Named("Relayer")
+ sugared := logger.Sugared(lggr).Named("Relayer").With("evmChainID", chain.ID())
mercuryORM := mercury.NewORM(opts.DS)
cdcFactory := sync.OnceValues(func() (llo.ChannelDefinitionCacheFactory, error) {
chainSelector, err := chainselectors.SelectorFromChainId(chain.ID().Uint64())
@@ -836,7 +836,7 @@ func (r *Relayer) NewConfigProvider(ctx context.Context, args commontypes.RelayA
// 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)
+ configProvider, err = newOCR3CapabilityConfigProvider(ctx, lggr, r.chain, relayOpts)
default:
return nil, fmt.Errorf("unrecognized provider type: %q", args.ProviderType)
}
diff --git a/core/services/relay/evm/llo/config_poller.go b/core/services/relay/evm/llo/config_poller.go
index 43d60210ace..9865bea8632 100644
--- a/core/services/relay/evm/llo/config_poller.go
+++ b/core/services/relay/evm/llo/config_poller.go
@@ -4,10 +4,12 @@ import (
"bytes"
"context"
"database/sql"
+ "encoding/hex"
"fmt"
"math"
"math/big"
"strconv"
+ "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
@@ -60,7 +62,8 @@ type configPoller struct {
donIDTopic [32]byte
filterExprs []query.Expression
- fromBlock uint64
+ fromBlock int64
+ mu sync.RWMutex
instanceType InstanceType
}
@@ -100,7 +103,7 @@ func newConfigPoller(lggr logger.Logger, lp LogPoller, cc ConfigCache, addr comm
donIDTopic: DonIDToBytes32(donID),
filterExprs: exprs,
instanceType: instanceType,
- fromBlock: fromBlock,
+ fromBlock: int64(fromBlock),
}
cp.Service, cp.eng = services.Config{
Name: "LLOConfigPoller",
@@ -115,11 +118,32 @@ func (cp *configPoller) Notify() <-chan struct{} {
// 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
+ latestConfig, log, err := cp.latestConfig(ctx, cp.readFromBlock(), math.MaxInt64)
if err != nil {
return 0, ocrtypes.ConfigDigest{}, fmt.Errorf("failed to get latest config: %w", err)
}
- return uint64(log.BlockNumber), latestConfig.ConfigDigest, nil
+ // Slight optimization, since we only care about the latest log, we can
+ // avoid re-scanning from the original fromBlock every time by setting
+ // fromBlock to the latest seen log here.
+ //
+ // This should always be safe even if LatestConfigDetails is called
+ // concurrently.
+ cp.setFromBlock(log.BlockNumber)
+ return uint64(log.BlockNumber), latestConfig.ConfigDigest, nil // #nosec G115 // log.BlockNumber will never be negative
+}
+
+func (cp *configPoller) readFromBlock() int64 {
+ cp.mu.RLock()
+ defer cp.mu.RUnlock()
+ return cp.fromBlock
+}
+
+func (cp *configPoller) setFromBlock(fromBlock int64) {
+ cp.mu.Lock()
+ defer cp.mu.Unlock()
+ if fromBlock > cp.fromBlock {
+ cp.fromBlock = fromBlock
+ }
}
func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int64) (latestConfig FullConfigFromLog, latestLog logpoller.Log, err error) {
@@ -150,7 +174,7 @@ func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int
}
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)
+ cp.eng.Errorf("failed to store production config: %v", err)
}
isProduction := (cp.instanceType != InstanceTypeBlue) == event.IsGreenProduction
@@ -168,7 +192,7 @@ func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int
}
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)
+ cp.eng.Errorf("failed to store staging config: %v", err)
}
isProduction := (cp.instanceType != InstanceTypeBlue) == event.IsGreenProduction
@@ -190,10 +214,11 @@ func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int
// 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
+ cfg, latestLog, 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)
}
+ cp.eng.Infow("LatestConfig fetched", "config", cfg.ContractConfig, "txHash", latestLog.TxHash, "blockNumber", latestLog.BlockNumber, "blockHash", latestLog.BlockHash, "logIndex", latestLog.LogIndex, "instanceType", cp.instanceType, "donID", cp.donID, "changedInBlock", changedInBlock)
return cfg.ContractConfig, nil
}
@@ -206,7 +231,7 @@ func (cp *configPoller) LatestBlockHeight(ctx context.Context) (blockHeight uint
}
return 0, err
}
- return uint64(latest.BlockNumber), nil
+ return uint64(latest.BlockNumber), nil // #nosec G115 // latest.BlockNumber will never be negative
}
func (cp *configPoller) InstanceType() InstanceType {
@@ -220,14 +245,13 @@ type FullConfigFromLog struct {
}
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)))
+ transmitAccounts := make([]ocrtypes.Account, len(unpacked.OffchainTransmitters))
+ for i, addr := range unpacked.OffchainTransmitters {
+ transmitAccounts[i] = ocrtypes.Account(hex.EncodeToString(addr[:]))
}
- var signers []ocrtypes.OnchainPublicKey
- for _, addr := range unpacked.Signers {
- addr := addr
- signers = append(signers, addr)
+ signers := make([]ocrtypes.OnchainPublicKey, len(unpacked.Signers))
+ for i, addr := range unpacked.Signers {
+ signers[i] = addr
}
donIDBig := common.Hash(unpacked.ConfigId).Big()
@@ -252,14 +276,13 @@ func FullConfigFromProductionConfigSet(unpacked configurator.ConfiguratorProduct
}
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)))
+ transmitAccounts := make([]ocrtypes.Account, len(unpacked.OffchainTransmitters))
+ for i, addr := range unpacked.OffchainTransmitters {
+ transmitAccounts[i] = ocrtypes.Account(hex.EncodeToString(addr[:]))
}
- var signers []ocrtypes.OnchainPublicKey
- for _, addr := range unpacked.Signers {
- addr := addr
- signers = append(signers, addr)
+ signers := make([]ocrtypes.OnchainPublicKey, len(unpacked.Signers))
+ for i, addr := range unpacked.Signers {
+ signers[i] = addr
}
donIDBig := common.Hash(unpacked.ConfigId).Big()
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 c3755b36809..260a8c25a24 100644
--- a/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go
+++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.35.1
-// protoc v4.25.1
+// protoc-gen-go v1.36.4
+// protoc v5.29.3
// source: mercury.proto
package pb
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -21,12 +22,11 @@ const (
)
type TransmitRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
+ ReportFormat uint32 `protobuf:"varint,2,opt,name=reportFormat,proto3" json:"reportFormat,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
- ReportFormat uint32 `protobuf:"varint,2,opt,name=reportFormat,proto3" json:"reportFormat,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *TransmitRequest) Reset() {
@@ -74,12 +74,11 @@ func (x *TransmitRequest) GetReportFormat() uint32 {
}
type TransmitResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+ Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
- Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *TransmitResponse) Reset() {
@@ -127,11 +126,10 @@ func (x *TransmitResponse) GetError() string {
}
type LatestReportRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ FeedId []byte `protobuf:"bytes,1,opt,name=feedId,proto3" json:"feedId,omitempty"`
unknownFields protoimpl.UnknownFields
-
- FeedId []byte `protobuf:"bytes,1,opt,name=feedId,proto3" json:"feedId,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *LatestReportRequest) Reset() {
@@ -172,12 +170,11 @@ func (x *LatestReportRequest) GetFeedId() []byte {
}
type LatestReportResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
+ Report *Report `protobuf:"bytes,2,opt,name=report,proto3" json:"report,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
- Report *Report `protobuf:"bytes,2,opt,name=report,proto3" json:"report,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *LatestReportResponse) Reset() {
@@ -225,24 +222,23 @@ func (x *LatestReportResponse) GetReport() *Report {
}
type Report struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- FeedId []byte `protobuf:"bytes,1,opt,name=feedId,proto3" json:"feedId,omitempty"`
- Price []byte `protobuf:"bytes,2,opt,name=price,proto3" json:"price,omitempty"`
- Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
- ValidFromBlockNumber int64 `protobuf:"varint,4,opt,name=validFromBlockNumber,proto3" json:"validFromBlockNumber,omitempty"`
- CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=currentBlockNumber,proto3" json:"currentBlockNumber,omitempty"`
- CurrentBlockHash []byte `protobuf:"bytes,6,opt,name=currentBlockHash,proto3" json:"currentBlockHash,omitempty"`
- CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=currentBlockTimestamp,proto3" json:"currentBlockTimestamp,omitempty"`
- ObservationsTimestamp int64 `protobuf:"varint,8,opt,name=observationsTimestamp,proto3" json:"observationsTimestamp,omitempty"`
- ConfigDigest []byte `protobuf:"bytes,9,opt,name=configDigest,proto3" json:"configDigest,omitempty"`
- Epoch uint32 `protobuf:"varint,10,opt,name=epoch,proto3" json:"epoch,omitempty"`
- Round uint32 `protobuf:"varint,11,opt,name=round,proto3" json:"round,omitempty"`
- OperatorName string `protobuf:"bytes,12,opt,name=operatorName,proto3" json:"operatorName,omitempty"`
- TransmittingOperator []byte `protobuf:"bytes,13,opt,name=transmittingOperator,proto3" json:"transmittingOperator,omitempty"`
- CreatedAt *Timestamp `protobuf:"bytes,14,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ state protoimpl.MessageState `protogen:"open.v1"`
+ FeedId []byte `protobuf:"bytes,1,opt,name=feedId,proto3" json:"feedId,omitempty"`
+ Price []byte `protobuf:"bytes,2,opt,name=price,proto3" json:"price,omitempty"`
+ Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
+ ValidFromBlockNumber int64 `protobuf:"varint,4,opt,name=validFromBlockNumber,proto3" json:"validFromBlockNumber,omitempty"`
+ CurrentBlockNumber int64 `protobuf:"varint,5,opt,name=currentBlockNumber,proto3" json:"currentBlockNumber,omitempty"`
+ CurrentBlockHash []byte `protobuf:"bytes,6,opt,name=currentBlockHash,proto3" json:"currentBlockHash,omitempty"`
+ CurrentBlockTimestamp uint64 `protobuf:"varint,7,opt,name=currentBlockTimestamp,proto3" json:"currentBlockTimestamp,omitempty"`
+ ObservationsTimestamp int64 `protobuf:"varint,8,opt,name=observationsTimestamp,proto3" json:"observationsTimestamp,omitempty"`
+ ConfigDigest []byte `protobuf:"bytes,9,opt,name=configDigest,proto3" json:"configDigest,omitempty"`
+ Epoch uint32 `protobuf:"varint,10,opt,name=epoch,proto3" json:"epoch,omitempty"`
+ Round uint32 `protobuf:"varint,11,opt,name=round,proto3" json:"round,omitempty"`
+ OperatorName string `protobuf:"bytes,12,opt,name=operatorName,proto3" json:"operatorName,omitempty"`
+ TransmittingOperator []byte `protobuf:"bytes,13,opt,name=transmittingOperator,proto3" json:"transmittingOperator,omitempty"`
+ CreatedAt *Timestamp `protobuf:"bytes,14,opt,name=createdAt,proto3" json:"createdAt,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *Report) Reset() {
@@ -375,10 +371,7 @@ func (x *Report) GetCreatedAt() *Timestamp {
// Taken from: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/timestamp.proto
type Timestamp struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
@@ -387,7 +380,9 @@ type Timestamp struct {
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
- Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *Timestamp) Reset() {
@@ -436,7 +431,7 @@ func (x *Timestamp) GetNanos() int32 {
var File_mercury_proto protoreflect.FileDescriptor
-var file_mercury_proto_rawDesc = []byte{
+var file_mercury_proto_rawDesc = string([]byte{
0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x02, 0x70, 0x62, 0x22, 0x4f, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x74, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61,
@@ -508,16 +503,16 @@ var file_mercury_proto_rawDesc = []byte{
0x72, 0x65, 0x6c, 0x61, 0x79, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72,
0x79, 0x2f, 0x77, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
-}
+})
var (
file_mercury_proto_rawDescOnce sync.Once
- file_mercury_proto_rawDescData = file_mercury_proto_rawDesc
+ file_mercury_proto_rawDescData []byte
)
func file_mercury_proto_rawDescGZIP() []byte {
file_mercury_proto_rawDescOnce.Do(func() {
- file_mercury_proto_rawDescData = protoimpl.X.CompressGZIP(file_mercury_proto_rawDescData)
+ file_mercury_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mercury_proto_rawDesc), len(file_mercury_proto_rawDesc)))
})
return file_mercury_proto_rawDescData
}
@@ -554,7 +549,7 @@ func file_mercury_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_mercury_proto_rawDesc,
+ RawDescriptor: unsafe.Slice(unsafe.StringData(file_mercury_proto_rawDesc), len(file_mercury_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
@@ -565,7 +560,6 @@ func file_mercury_proto_init() {
MessageInfos: file_mercury_proto_msgTypes,
}.Build()
File_mercury_proto = out.File
- file_mercury_proto_rawDesc = nil
file_mercury_proto_goTypes = nil
file_mercury_proto_depIdxs = nil
}
diff --git a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go b/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go
index 4d05db4380f..1e0a862f487 100644
--- a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go
+++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury_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.29.3
package pb
diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go
index 8b7e79c1fc5..2a5199de851 100644
--- a/core/services/relay/evm/relayer_extender.go
+++ b/core/services/relay/evm/relayer_extender.go
@@ -43,7 +43,7 @@ func NewLegacyChains(ctx context.Context, opts legacyevm.ChainRelayOpts) (result
unique := make(map[string]struct{})
- evmConfigs := opts.AppConfig.EVMConfigs()
+ evmConfigs := opts.ChainConfigs
var enabled []*toml.EVMConfig
for i, cfg := range evmConfigs {
_, alreadyExists := unique[cfg.ChainID.String()]
@@ -81,5 +81,5 @@ func NewLegacyChains(ctx context.Context, opts legacyevm.ChainRelayOpts) (result
func NewLegacyChainsAndConfig(ctx context.Context, opts legacyevm.ChainRelayOpts) (*LegacyChainsAndConfig, error) {
result, err := NewLegacyChains(ctx, opts)
// always return because it's accumulating errors
- return &LegacyChainsAndConfig{result, opts.AppConfig.EVMConfigs()}, err
+ return &LegacyChainsAndConfig{result, opts.ChainConfigs}, err
}
diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go
index 9a65b486da7..0bda7825c71 100644
--- a/core/services/relay/evm/relayer_extender_test.go
+++ b/core/services/relay/evm/relayer_extender_test.go
@@ -38,7 +38,7 @@ func TestChainRelayExtenders(t *testing.T) {
opts := evmtest.NewChainOpts(t, evmtest.TestChainOpts{
DB: db,
KeyStore: kst.Eth(),
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go
index 77deaf051c7..99a915c2376 100644
--- a/core/services/relay/evm/write_target_test.go
+++ b/core/services/relay/evm/write_target_test.go
@@ -264,12 +264,12 @@ func TestEvmWrite(t *testing.T) {
testChain := evmmocks.NewChain(t)
testCfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].Workflow.FromAddress = nil
-
forwarderA := testutils.NewAddress()
forwarderAddr, err2 := evmtypes.NewEIP55Address(forwarderA.Hex())
require.NoError(t, err2)
c.EVM[0].Workflow.ForwarderAddress = &forwarderAddr
})
+ testChain.On("ID").Return(big.NewInt(11155111))
testChain.On("Config").Return(evmtest.NewChainScopedConfig(t, testCfg))
capabilityRegistry := evmcapabilities.NewRegistry(lggr)
diff --git a/core/services/standardcapabilities/delegate.go b/core/services/standardcapabilities/delegate.go
index 914324c9170..1f14db4c6a4 100644
--- a/core/services/standardcapabilities/delegate.go
+++ b/core/services/standardcapabilities/delegate.go
@@ -12,7 +12,6 @@ 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"
@@ -49,7 +48,8 @@ type Delegate struct {
gatewayConnectorWrapper *gatewayconnector.ServiceWrapper
ks keystore.Master
peerWrapper *ocrcommon.SingletonPeerWrapper
- newOracleFactoryFn func(generic.OracleFactoryParams) (core.OracleFactory, error)
+ newOracleFactoryFn NewOracleFactoryFn
+ computeFetcherFactoryFn compute.FetcherFactory
isNewlyCreatedJob bool
}
@@ -75,6 +75,7 @@ func NewDelegate(
ks keystore.Master,
peerWrapper *ocrcommon.SingletonPeerWrapper,
newOracleFactoryFn NewOracleFactoryFn,
+ fetcherFactoryFn compute.FetcherFactory,
) *Delegate {
return &Delegate{
logger: logger,
@@ -90,6 +91,7 @@ func NewDelegate(
ks: ks,
peerWrapper: peerWrapper,
newOracleFactoryFn: newOracleFactoryFn,
+ computeFetcherFactoryFn: fetcherFactoryFn,
}
}
@@ -230,35 +232,51 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser
}
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 fetcherFactoryFn compute.FetcherFactory
+ var services []job.ServiceCtx
var cfg compute.Config
- err := toml.Unmarshal([]byte(spec.StandardCapabilitiesSpec.Config), &cfg)
- if err != nil {
- return nil, err
+
+ tomlErr := toml.Unmarshal([]byte(spec.StandardCapabilitiesSpec.Config), &cfg)
+ if tomlErr != nil {
+ return nil, tomlErr
}
- lggr := d.logger.Named("ComputeAction")
- handler, err := webapi.NewOutgoingConnectorHandler(d.gatewayConnectorWrapper.GetGatewayConnector(), cfg.ServiceConfig, capabilities.MethodComputeAction, lggr)
- if err != nil {
- return nil, err
+ if d.computeFetcherFactoryFn != nil {
+ fetcherFactoryFn = d.computeFetcherFactoryFn
+ } else {
+ if d.gatewayConnectorWrapper == nil {
+ return nil, errors.New("gateway connector is required for custom compute capability")
+ }
+
+ lggr := d.logger.Named("ComputeAction")
+
+ handler, err := webapi.NewOutgoingConnectorHandler(d.gatewayConnectorWrapper.GetGatewayConnector(), cfg.ServiceConfig, capabilities.MethodComputeAction, lggr)
+ if err != nil {
+ return nil, err
+ }
+ services = append(services, handler)
+
+ idGeneratorFn := func() string {
+ return uuid.New().String()
+ }
+
+ fetcherFactoryFn, err = compute.NewOutgoingConnectorFetcherFactory(handler, idGeneratorFn)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create fetcher factory: %w", err)
+ }
}
- idGeneratorFn := func() string {
- return uuid.New().String()
+ if len(spec.StandardCapabilitiesSpec.Config) == 0 {
+ return nil, errors.New("config is empty")
}
- computeSrvc, err := compute.NewAction(cfg, log, d.registry, handler, idGeneratorFn)
+ computeSrvc, err := compute.NewAction(cfg, log, d.registry, fetcherFactoryFn)
if err != nil {
return nil, err
}
- return []job.ServiceCtx{handler, computeSrvc}, nil
+ services = append(services, computeSrvc)
+
+ return services, nil
}
standardCapability := newStandardCapabilities(log, spec.StandardCapabilitiesSpec, d.cfg, telemetryService, kvStore, d.registry, errorLog,
diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go
index cebf2446309..6f8d4cfc714 100644
--- a/core/services/vrf/delegate_test.go
+++ b/core/services/vrf/delegate_test.go
@@ -92,7 +92,7 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv
KeyStore: ks.Eth(),
Client: ec,
DB: db,
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go
index d06ee65278c..fd73a3e7504 100644
--- a/core/services/vrf/v2/integration_v2_test.go
+++ b/core/services/vrf/v2/integration_v2_test.go
@@ -2107,7 +2107,7 @@ func TestStartingCountsV1(t *testing.T) {
KeyStore: ks.Eth(),
Client: ec,
DB: db,
- GeneralConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
FeatureConfig: cfg.Feature(),
ListenerConfig: cfg.Database().Listener(),
diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go
index b3b9dd40282..0a58887a361 100644
--- a/core/services/vrf/v2/listener_v2_test.go
+++ b/core/services/vrf/v2/listener_v2_test.go
@@ -14,15 +14,14 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null"
-
txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr"
txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types"
+
"github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr"
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2"
"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/logger"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
@@ -30,13 +29,14 @@ 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/evm/client/clienttest"
"github.com/smartcontractkit/chainlink/v2/evm/gas"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
)
func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.Master) txmgrcommon.TxManager[*big.Int, *evmtypes.Head, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] {
_, _, evmConfig := txmgr.MakeTestConfigs(t)
- ec := evmtest.NewEthClientMockWithDefaultChain(t)
+ ec := clienttest.NewClientWithDefaultChainID(t)
txmConfig := txmgr.NewEvmTxmConfig(evmConfig)
txm := txmgr.NewEvmTxm(ec.ConfiguredChainID(), txmConfig, evmConfig.Transactions(), keyStore.Eth(), logger.TestLogger(t), nil, nil,
nil, txStore, nil, nil, nil, nil, nil, nil)
diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go
index 3fdf0059ca4..abf4e59579d 100644
--- a/core/services/workflows/engine.go
+++ b/core/services/workflows/engine.go
@@ -470,6 +470,9 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig
}}
}
+ // mark the trigger as successfully registered
+ t.registered = true
+
e.wg.Add(1)
go func() {
defer e.wg.Done()
@@ -1037,10 +1040,10 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr
Config: t.config.Load(),
}
- // if t.trigger == nil, then we haven't initialized the workflow
+ // if t.trigger == nil or !t.registered, then we haven't initialized the workflow
// yet, and can safely consider the trigger deregistered with
// no further action.
- if t.trigger != nil {
+ if t.trigger != nil && t.registered {
return t.trigger.UnregisterTrigger(ctx, deregRequest)
}
diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go
index c3c6ff87232..0cfc4ff88b3 100644
--- a/core/services/workflows/engine_test.go
+++ b/core/services/workflows/engine_test.go
@@ -270,13 +270,15 @@ func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request cap
type mockTriggerCapability struct {
capabilities.CapabilityInfo
- triggerEvent *capabilities.TriggerResponse
- ch chan capabilities.TriggerResponse
+ triggerEvent *capabilities.TriggerResponse
+ ch chan capabilities.TriggerResponse
+ registerTriggerCallCounter map[string]int
}
var _ capabilities.TriggerCapability = (*mockTriggerCapability)(nil)
func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) (<-chan capabilities.TriggerResponse, error) {
+ m.registerTriggerCallCounter[req.TriggerID]++
if m.triggerEvent != nil {
m.ch <- *m.triggerEvent
}
@@ -284,6 +286,9 @@ func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabil
}
func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capabilities.TriggerRegistrationRequest) error {
+ if m.registerTriggerCallCounter[req.TriggerID] == 0 {
+ return errors.New("failed to unregister a non-registered trigger")
+ }
return nil
}
@@ -384,7 +389,8 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Tri
capabilities.CapabilityTypeTrigger,
"issues a trigger when a mercury report is received.",
),
- ch: make(chan capabilities.TriggerResponse, 10),
+ ch: make(chan capabilities.TriggerResponse, 10),
+ registerTriggerCallCounter: make(map[string]int),
}
resp, err := values.NewMap(map[string]any{
"123": decimal.NewFromFloat(1.00),
@@ -410,7 +416,8 @@ func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability {
capabilities.CapabilityTypeTrigger,
"issues a trigger when a mercury report is received.",
),
- ch: make(chan capabilities.TriggerResponse, 10),
+ ch: make(chan capabilities.TriggerResponse, 10),
+ registerTriggerCallCounter: make(map[string]int),
}
return mt
}
@@ -1542,7 +1549,8 @@ func basicTestTrigger(t *testing.T) *mockTriggerCapability {
capabilities.CapabilityTypeTrigger,
"basic test trigger",
),
- ch: make(chan capabilities.TriggerResponse, 10),
+ ch: make(chan capabilities.TriggerResponse, 10),
+ registerTriggerCallCounter: make(map[string]int),
}
resp, err := values.NewMap(map[string]any{
@@ -1586,7 +1594,9 @@ func TestEngine_WithCustomComputeStep(t *testing.T) {
require.NoError(t, err)
idGeneratorFn := func() string { return "validRequestID" }
- compute, err := compute.NewAction(cfg, log, reg, handler, idGeneratorFn)
+ fetcher, err := compute.NewOutgoingConnectorFetcherFactory(handler, idGeneratorFn)
+ require.NoError(t, err)
+ compute, err := compute.NewAction(cfg, log, reg, fetcher)
require.NoError(t, err)
require.NoError(t, compute.Start(ctx))
defer compute.Close()
@@ -1652,7 +1662,9 @@ func TestEngine_CustomComputePropagatesBreaks(t *testing.T) {
require.NoError(t, err)
idGeneratorFn := func() string { return "validRequestID" }
- compute, err := compute.NewAction(cfg, log, reg, handler, idGeneratorFn)
+ fetcher, err := compute.NewOutgoingConnectorFetcherFactory(handler, idGeneratorFn)
+ require.NoError(t, err)
+ compute, err := compute.NewAction(cfg, log, reg, fetcher)
require.NoError(t, err)
require.NoError(t, compute.Start(ctx))
defer compute.Close()
@@ -1741,10 +1753,11 @@ targets:
type mockFetcher struct {
retval map[string]string
+ retErr error
}
func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, hexWorkflowName, decodedWorkflowName, workflowID string) (map[string]string, error) {
- return m.retval, nil
+ return m.retval, m.retErr
}
func TestEngine_FetchesSecrets(t *testing.T) {
@@ -1779,34 +1792,86 @@ func TestEngine_FetchesSecrets(t *testing.T) {
)
require.NoError(t, reg.Add(ctx, action))
+ t.Run("successfully fetches secrets", func(t *testing.T) {
+ eng, testHooks := newTestEngineWithYAMLSpec(
+ t,
+ reg,
+ secretsWorkflow,
+ func(c *Config) {
+ c.SecretsFetcher = &mockFetcher{
+ retval: map[string]string{
+ "fidelity": "aFidelitySecret",
+ },
+ }
+ },
+ )
+
+ servicetest.Run(t, eng)
+
+ eid := getExecutionID(t, eng, testHooks)
+
+ state, err := eng.executionStates.Get(ctx, eid)
+ require.NoError(t, err)
+
+ assert.Equal(t, store.StatusCompleted, state.Status)
+
+ expected := map[string]any{
+ "fidelityToken": "aFidelitySecret",
+ }
+ expm, err := values.Wrap(expected)
+ require.NoError(t, err)
+ assert.Equal(t, gotConfig, expm)
+ })
+}
+
+func TestEngine_CloseHappensOnlyIfWorkflowHasBeenRegistered(t *testing.T) {
+ 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("")))
+
+ target := mockTarget("write_ethereum-testnet-sepolia@1.0.0")
+ require.NoError(t, reg.Add(ctx, target))
+
+ action := newMockCapability(
+ // Create a remote capability so we don't use the local transmission protocol.
+ capabilities.MustNewRemoteCapabilityInfo(
+ "custom-compute@1.0.0",
+ capabilities.CapabilityTypeAction,
+ "a custom compute action with custom config",
+ &capabilities.DON{ID: 1},
+ ),
+ func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) {
+ return capabilities.CapabilityResponse{
+ Value: req.Inputs,
+ }, nil
+ },
+ )
+ require.NoError(t, reg.Add(ctx, action))
+
eng, testHooks := newTestEngineWithYAMLSpec(
t,
reg,
secretsWorkflow,
func(c *Config) {
c.SecretsFetcher = &mockFetcher{
- retval: map[string]string{
- "fidelity": "aFidelitySecret",
- },
+ retval: map[string]string{},
+ retErr: errors.New("failed to fetch secrets XXX"),
}
},
)
- servicetest.Run(t, eng)
-
- eid := getExecutionID(t, eng, testHooks)
-
- state, err := eng.executionStates.Get(ctx, eid)
+ err := eng.Start(ctx)
require.NoError(t, err)
- assert.Equal(t, store.StatusCompleted, state.Status)
-
- expected := map[string]any{
- "fidelityToken": "aFidelitySecret",
- }
- expm, err := values.Wrap(expected)
+ // simulate WorkflowUpdatedEvent that calls tryEngineCleanup
+ <-testHooks.initFailed
+ err = eng.Close()
require.NoError(t, err)
- assert.Equal(t, gotConfig, expm)
}
func TestMerge(t *testing.T) {
diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go
index d8abb0e9073..e14ad257819 100644
--- a/core/services/workflows/models.go
+++ b/core/services/workflows/models.go
@@ -116,6 +116,9 @@ type triggerCapability struct {
sdk.StepDefinition
trigger capabilities.TriggerCapability
+ // flag to track registration of the trigger and avoid removal of non registered triggers
+ registered bool
+
config atomic.Pointer[values.Map]
}
diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go
index 3236a65f913..65ecdf1f467 100644
--- a/core/services/workflows/syncer/workflow_registry.go
+++ b/core/services/workflows/syncer/workflow_registry.go
@@ -90,7 +90,7 @@ type WorkflowLoadConfig struct {
}
// FetcherFunc is an abstraction for fetching the contents stored at a URL.
-type FetcherFunc func(ctx context.Context, url string, n uint32) ([]byte, error)
+type FetcherFunc func(ctx context.Context, url string, maxBytesSize uint32) ([]byte, error)
// ContractReader is a subset of types.ContractReader defined locally to enable mocking.
type ContractReader interface {
diff --git a/core/store/store.go b/core/store/store.go
new file mode 100644
index 00000000000..76c74abc23b
--- /dev/null
+++ b/core/store/store.go
@@ -0,0 +1,8 @@
+package store
+
+import _ "embed"
+
+//go:embed fixtures/fixtures.sql
+var fixturesSQL string
+
+func FixturesSQL() string { return fixturesSQL }
diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go
index ff1f96ce080..e8a58bb4eea 100644
--- a/core/testdata/testspecs/v2_specs.go
+++ b/core/testdata/testspecs/v2_specs.go
@@ -186,9 +186,81 @@ schemaVersion = 1
contractID = "0x613a38AC1659769640aaE063C651F48E0250454C"
[relayConfig]
chainID = 1337
+`
+
+ GatewaySpec = `
+type = "gateway"
+schemaVersion = 1
+externalJobID = "%s"
+name = "Gateway"
+forwardingAllowed = false
+[gatewayConfig.ConnectionManagerConfig]
+AuthChallengeLen = 10
+AuthGatewayId = "%s"
+AuthTimestampToleranceSec = 5
+HeartbeatIntervalSec = 20
+[[gatewayConfig.Dons]]
+DonId = "1"
+F = 1
+HandlerName = "web-api-capabilities"
+ [gatewayConfig.Dons.HandlerConfig]
+ MaxAllowedMessageAgeSec = 1_000
+ [gatewayConfig.Dons.HandlerConfig.NodeRateLimiter]
+ GlobalBurst = 10
+ GlobalRPS = 50
+ PerSenderBurst = 10
+ PerSenderRPS = 10
+ [[gatewayConfig.Dons.Members]]
+ Address = "%s"
+ Name = "Workflow Node 1"
+ [[gatewayConfig.Dons.Members]]
+ Address = "%s"
+ Name = "Workflow Node 2"
+ [[gatewayConfig.Dons.Members]]
+ Address = "%s"
+ Name = "Workflow Node 3"
+ [[gatewayConfig.Dons.Members]]
+ Address = "%s"
+ Name = "Workflow Node 4"
+[gatewayConfig.NodeServerConfig]
+HandshakeTimeoutMillis = 1_000
+MaxRequestBytes = 100_000
+Path = "%s"
+Port = %d
+ReadTimeoutMillis = 1_000
+RequestTimeoutMillis = 10_000
+WriteTimeoutMillis = 1_000
+[gatewayConfig.UserServerConfig]
+ContentTypeHeader = "application/jsonrpc"
+MaxRequestBytes = 100_000
+Path = "%s"
+Port = %d
+ReadTimeoutMillis = 1_000
+RequestTimeoutMillis = 10_000
+WriteTimeoutMillis = 1_000
+[gatewayConfig.HTTPClientConfig]
+MaxResponseBytes = 100_000_000
+`
+
+ StandardCapabilitySpec = `
+type = "standardcapabilities"
+schemaVersion = 1
+externalJobID = "%s"
+name = "%s"
+forwardingAllowed = false
+command = "/home/capabilities/%s"
+config = "%s"
`
)
+func GetStandardCapabilitySpec() string {
+ return fmt.Sprintf(StandardCapabilitySpec, uuid.New(), "some-capability", "some_capability_linux_amd64", "")
+}
+
+func GetGatewaySpec() string {
+ return fmt.Sprintf(GatewaySpec, uuid.New(), "gateway", "0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca1", "0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca2", "0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca3", "0xABA5eDc1a551E55b1A570c0e1f1055e5BE11eca4", "/node", 8080, "/user", 8081)
+}
+
func GetOCRBootstrapSpec() string {
return fmt.Sprintf(OCRBootstrapSpec, uuid.New())
}
@@ -948,7 +1020,7 @@ targets:
- id: "a-target@1.0.0"
config: {}
ref: "a-target"
- inputs:
+ inputs:
consensus_output: $(a-consensus.outputs)
`
var OCR2EVMDualTransmissionSpecMinimalTemplate = `
diff --git a/core/utils/testutils/heavyweight/orm.go b/core/utils/testutils/heavyweight/orm.go
index 970ec1c89d6..e8266ccf16b 100644
--- a/core/utils/testutils/heavyweight/orm.go
+++ b/core/utils/testutils/heavyweight/orm.go
@@ -4,8 +4,6 @@ package heavyweight
import (
"os"
- "path"
- "runtime"
"strings"
"testing"
@@ -14,10 +12,11 @@ import (
"github.com/jmoiron/sqlx"
+ commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config"
pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg"
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink/v2/core/store"
- "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/pg"
@@ -28,32 +27,27 @@ import (
// FullTestDBV2 creates a pristine DB which runs in a separate database than the normal
// unit tests, so you can do things like use other Postgres connection types with it.
func FullTestDBV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return KindFixtures.PrepareDB(t, overrideFn)
+ cfg, db := FullTestDBNoFixturesV2(t, overrideFn)
+ _, err := db.Exec(store.FixturesSQL())
+ require.NoError(t, err)
+ return cfg, db
}
// FullTestDBNoFixturesV2 is the same as FullTestDB, but it does not load fixtures.
func FullTestDBNoFixturesV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return KindTemplate.PrepareDB(t, overrideFn)
+ return prepareDB(t, true, overrideFn)
}
// FullTestDBEmptyV2 creates an empty DB (without migrations).
func FullTestDBEmptyV2(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
- return KindEmpty.PrepareDB(t, overrideFn)
+ return prepareDB(t, false, overrideFn)
}
func generateName() string {
- return strings.ReplaceAll(uuid.New().String(), "-", "")
+ return strings.ReplaceAll(uuid.NewString(), "-", "")
}
-type Kind int
-
-const (
- KindEmpty Kind = iota
- KindTemplate
- KindFixtures
-)
-
-func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
+func prepareDB(t testing.TB, withTemplate bool, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) {
tests.SkipShort(t, "FullTestDB")
gcfg := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
@@ -64,35 +58,21 @@ func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *ch
})
require.NoError(t, os.MkdirAll(gcfg.RootDir(), 0700))
- migrationTestDBURL, err := testdb.CreateOrReplace(gcfg.Database().URL(), generateName(), c != KindEmpty)
- require.NoError(t, err)
- db, err := pg.NewConnection(tests.Context(t), migrationTestDBURL, pgcommon.DriverPostgres, gcfg.Database())
+ t.Cleanup(func() { os.RemoveAll(gcfg.RootDir()) })
+
+ migrationTestDBURL := testdb.CreateOrReplace(t, gcfg.Database().URL(), generateName(), withTemplate)
+ db, err := pg.NewConnection(tests.Context(t), migrationTestDBURL.String(), pgcommon.DriverPostgres, gcfg.Database())
require.NoError(t, err)
- t.Cleanup(func() {
- require.NoError(t, db.Close()) // must close before dropping
- require.NoError(t, testdb.Drop(*testutils.MustParseURL(t, migrationTestDBURL)))
- os.RemoveAll(gcfg.RootDir())
- })
+ t.Cleanup(func() { require.NoError(t, db.Close()) }) // must close before dropping
+ // reset with new URL
gcfg = configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.Database.DriverName = pgcommon.DriverPostgres
- s.Database.URL = models.MustSecretURL(migrationTestDBURL)
+ s.Database.URL = models.NewSecretURL((*commoncfg.URL)(&migrationTestDBURL))
if overrideFn != nil {
overrideFn(c, s)
}
})
- if c == KindFixtures {
- _, filename, _, ok := runtime.Caller(1)
- if !ok {
- t.Fatal("could not get runtime.Caller(1)")
- }
- filepath := path.Join(path.Dir(filename), "../../../store/fixtures/fixtures.sql")
- fixturesSQL, err := os.ReadFile(filepath)
- require.NoError(t, err)
- _, err = db.Exec(string(fixturesSQL))
- require.NoError(t, err)
- }
-
return gcfg, db
}
diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go
index 78982e2e304..4dd5d7969b7 100644
--- a/core/web/eth_keys_controller_test.go
+++ b/core/web/eth_keys_controller_test.go
@@ -1,12 +1,16 @@
package web_test
import (
+ "errors"
"math/big"
"net/http"
"net/url"
"testing"
- "github.com/pkg/errors"
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
"github.com/smartcontractkit/chainlink-common/pkg/assets"
commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks"
@@ -15,17 +19,11 @@ import (
"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/evmtest"
"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"
webpresenters "github.com/smartcontractkit/chainlink/v2/core/web/presenters"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
-
- "github.com/google/uuid"
+ "github.com/smartcontractkit/chainlink/v2/evm/client/clienttest"
)
func TestETHKeysController_Index_Success(t *testing.T) {
@@ -217,7 +215,7 @@ func TestETHKeysController_CreateSuccess(t *testing.T) {
config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {
c.EVM[0].BalanceMonitor.Enabled = ptr(false)
})
- ethClient := evmtest.NewEthClientMockWithDefaultChain(t)
+ ethClient := clienttest.NewClientWithDefaultChainID(t)
app := cltest.NewApplicationWithConfigAndKey(t, config, ethClient)
sub := commonmocks.NewSubscription(t)
diff --git a/dashboard-lib/core-node-components/component.go b/dashboard-lib/core-node-components/component.go
index 47e23c073ba..5452a1c257f 100644
--- a/dashboard-lib/core-node-components/component.go
+++ b/dashboard-lib/core-node-components/component.go
@@ -114,7 +114,7 @@ func generalInfoRow(p Props) []dashboard.Option {
),
timeseries.WithPrometheusTarget(
`up{`+p.PlatformOpts.LabelQuery+`}`,
- //prometheus.Legend(""),
+ // prometheus.Legend(""),
prometheus.Legend("Team: {{team}} env: {{env}} cluster: {{cluster}} namespace: {{namespace}} job: {{job}} blockchain: {{blockchain}} product: {{product}} networkType: {{network_type}} component: {{component}} service: {{service}}"),
),
),
diff --git a/dashboard-lib/k8s-pods/component.go b/dashboard-lib/k8s-pods/component.go
index df9a6ac6a69..559a89f4538 100644
--- a/dashboard-lib/k8s-pods/component.go
+++ b/dashboard-lib/k8s-pods/component.go
@@ -68,7 +68,6 @@ func logsRow(p Props) []dashboard.Option {
),
),
}
-
}
func New(p Props) []dashboard.Option {
diff --git a/deployment/address_book.go b/deployment/address_book.go
index fde0adc2d97..e123a2116bd 100644
--- a/deployment/address_book.go
+++ b/deployment/address_book.go
@@ -32,16 +32,36 @@ var (
)
type TypeAndVersion struct {
- Type ContractType
- Version semver.Version
+ Type ContractType `json:"type"`
+ Version semver.Version `json:"version"`
+ Labels LabelSet `json:"labels,omitempty"`
}
func (tv TypeAndVersion) String() string {
- return fmt.Sprintf("%s %s", tv.Type, tv.Version.String())
+ if len(tv.Labels) == 0 {
+ return fmt.Sprintf("%s %s", tv.Type, tv.Version.String())
+ }
+
+ // Use the LabelSet's String method for sorted labels
+ sortedLabels := tv.Labels.String()
+ return fmt.Sprintf("%s %s %s",
+ tv.Type,
+ tv.Version.String(),
+ sortedLabels,
+ )
}
func (tv TypeAndVersion) Equal(other TypeAndVersion) bool {
- return tv.String() == other.String()
+ // Compare Type
+ if tv.Type != other.Type {
+ return false
+ }
+ // Compare Versions
+ if !tv.Version.Equal(&other.Version) {
+ return false
+ }
+ // Compare Labels
+ return tv.Labels.Equal(other.Labels)
}
func MustTypeAndVersionFromString(s string) TypeAndVersion {
@@ -55,17 +75,22 @@ func MustTypeAndVersionFromString(s string) TypeAndVersion {
// 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 {
+ parts := strings.Fields(s) // Ignores consecutive spaces
+ 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
}
+ labels := make(LabelSet)
+ if len(parts) > 2 {
+ labels = NewLabelSet(parts[2:]...)
+ }
return TypeAndVersion{
Type: ContractType(parts[0]),
Version: *v,
+ Labels: labels,
}, nil
}
@@ -73,6 +98,7 @@ func NewTypeAndVersion(t ContractType, v semver.Version) TypeAndVersion {
return TypeAndVersion{
Type: t,
Version: v,
+ Labels: make(LabelSet), // empty set,
}
}
@@ -274,25 +300,49 @@ func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool,
return false, nil
}
+type typeVersionKey struct {
+ Type ContractType
+ Version string
+ Labels string // store labels in a canonical form (comma-joined sorted list)
+}
+
+func tvKey(tv TypeAndVersion) typeVersionKey {
+ sortedLabels := tv.Labels.String()
+ return typeVersionKey{
+ Type: tv.Type,
+ Version: tv.Version.String(),
+ Labels: sortedLabels,
+ }
+}
+
// AddressesContainBundle checks if the addresses
// contains a single instance of all the addresses in the bundle.
// It returns an error if there are more than one instance of a contract.
-func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes map[TypeAndVersion]struct{}) (bool, error) {
- counts := make(map[TypeAndVersion]int)
- for wantType := range wantTypes {
- for _, haveType := range addrs {
- if wantType == haveType {
- counts[wantType]++
- if counts[wantType] > 1 {
- return false, fmt.Errorf("found more than one instance of contract %s", wantType)
+func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes []TypeAndVersion) (bool, error) {
+ // Count how many times each wanted TypeAndVersion is found
+ counts := make(map[typeVersionKey]int)
+ for _, wantTV := range wantTypes {
+ wantKey := tvKey(wantTV)
+ for _, haveTV := range addrs {
+ if wantTV.Equal(haveTV) {
+ // They match exactly (Type, Version, Labels)
+ counts[wantKey]++
+ if counts[wantKey] > 1 {
+ return false, fmt.Errorf("found more than one instance of contract %s %s (labels=%s)",
+ wantTV.Type, wantTV.Version.String(), wantTV.Labels.String())
}
}
}
}
- // Either 0 or 1, so we can just check the sum.
- sum := 0
- for _, count := range counts {
- sum += count
+
+ // Ensure we found *all* wantTypes exactly once
+ return len(counts) == len(wantTypes), nil
+}
+
+// AddLabel adds a string to the LabelSet in the TypeAndVersion.
+func (tv *TypeAndVersion) AddLabel(label string) {
+ if tv.Labels == nil {
+ tv.Labels = make(LabelSet)
}
- return sum == len(wantTypes), nil
+ tv.Labels.Add(label)
}
diff --git a/deployment/address_book_labels.go b/deployment/address_book_labels.go
new file mode 100644
index 00000000000..f559a39078a
--- /dev/null
+++ b/deployment/address_book_labels.go
@@ -0,0 +1,67 @@
+package deployment
+
+import (
+ "sort"
+ "strings"
+)
+
+// LabelSet represents a set of labels on an address book entry.
+type LabelSet map[string]struct{}
+
+// NewLabelSet initializes a new LabelSet with any number of labels.
+func NewLabelSet(labels ...string) LabelSet {
+ set := make(LabelSet)
+ for _, lb := range labels {
+ set[lb] = struct{}{}
+ }
+ return set
+}
+
+// Add inserts a labels into the set.
+func (ls LabelSet) Add(labels string) {
+ ls[labels] = struct{}{}
+}
+
+// Remove deletes a labels from the set, if it exists.
+func (ls LabelSet) Remove(labels string) {
+ delete(ls, labels)
+}
+
+// Contains checks if the set contains the given labels.
+func (ls LabelSet) Contains(labels string) bool {
+ _, ok := ls[labels]
+ return ok
+}
+
+// String returns the labels as a sorted, space-separated string.
+// It implements the fmt.Stringer interface.
+func (ls LabelSet) String() string {
+ if len(ls) == 0 {
+ return ""
+ }
+
+ // Collect labels into a slice
+ labels := make([]string, 0, len(ls))
+ for label := range ls {
+ labels = append(labels, label)
+ }
+
+ // Sort the labels to ensure consistent ordering
+ sort.Strings(labels)
+
+ // Concatenate the sorted labels into a single string
+ return strings.Join(labels, " ")
+}
+
+// Equal checks if two LabelSets are equal.
+func (ls LabelSet) Equal(other LabelSet) bool {
+ if len(ls) != len(other) {
+ return false
+ }
+ for label := range ls {
+ if _, ok := other[label]; !ok {
+ return false
+ }
+ }
+ return true
+}
diff --git a/deployment/address_book_labels_test.go b/deployment/address_book_labels_test.go
new file mode 100644
index 00000000000..f42e3568cba
--- /dev/null
+++ b/deployment/address_book_labels_test.go
@@ -0,0 +1,183 @@
+package deployment
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewLabelSet(t *testing.T) {
+ t.Run("no labels", func(t *testing.T) {
+ ms := NewLabelSet()
+ assert.Empty(t, ms, "expected empty set")
+ })
+
+ t.Run("some labels", func(t *testing.T) {
+ ms := NewLabelSet("foo", "bar")
+ assert.Len(t, ms, 2)
+ assert.True(t, ms.Contains("foo"))
+ assert.True(t, ms.Contains("bar"))
+ assert.False(t, ms.Contains("baz"))
+ })
+}
+
+func TestLabelSet_Add(t *testing.T) {
+ ms := NewLabelSet("initial")
+ ms.Add("new")
+
+ assert.True(t, ms.Contains("initial"), "expected 'initial' in set")
+ assert.True(t, ms.Contains("new"), "expected 'new' in set")
+ assert.Len(t, ms, 2, "expected 2 distinct labels in set")
+
+ // Add duplicate "new" again; size should remain 2
+ ms.Add("new")
+ assert.Len(t, ms, 2, "expected size to remain 2 after adding a duplicate")
+}
+
+func TestLabelSet_Remove(t *testing.T) {
+ ms := NewLabelSet("remove_me", "keep")
+ ms.Remove("remove_me")
+
+ assert.False(t, ms.Contains("remove_me"), "expected 'remove_me' to be removed")
+ assert.True(t, ms.Contains("keep"), "expected 'keep' to remain")
+ assert.Len(t, ms, 1, "expected set size to be 1 after removal")
+
+ // Removing a non-existent item shouldn't change the size
+ ms.Remove("non_existent")
+ assert.Len(t, ms, 1, "expected size to remain 1 after removing a non-existent item")
+}
+
+func TestLabelSet_Contains(t *testing.T) {
+ ms := NewLabelSet("foo", "bar")
+
+ assert.True(t, ms.Contains("foo"))
+ assert.True(t, ms.Contains("bar"))
+ assert.False(t, ms.Contains("baz"))
+}
+
+// TestLabelSet_String tests the String() method of the LabelSet type.
+func TestLabelSet_String(t *testing.T) {
+ tests := []struct {
+ name string
+ labels LabelSet
+ expected string
+ }{
+ {
+ name: "Empty LabelSet",
+ labels: NewLabelSet(),
+ expected: "",
+ },
+ {
+ name: "Single label",
+ labels: NewLabelSet("alpha"),
+ expected: "alpha",
+ },
+ {
+ name: "Multiple labels in random order",
+ labels: NewLabelSet("beta", "gamma", "alpha"),
+ expected: "alpha beta gamma",
+ },
+ {
+ name: "Labels with special characters",
+ labels: NewLabelSet("beta", "gamma!", "@alpha"),
+ expected: "@alpha beta gamma!",
+ },
+ {
+ name: "Labels with spaces",
+ labels: NewLabelSet("beta", "gamma delta", "alpha"),
+ expected: "alpha beta gamma delta",
+ },
+ {
+ name: "Labels added in different orders",
+ labels: NewLabelSet("delta", "beta", "alpha"),
+ expected: "alpha beta delta",
+ },
+ {
+ name: "Labels with duplicate additions",
+ labels: NewLabelSet("alpha", "beta", "alpha", "gamma", "beta"),
+ expected: "alpha beta gamma",
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ result := tt.labels.String()
+ assert.Equal(t, tt.expected, result, "LabelSet.String() should return the expected sorted string")
+ })
+ }
+}
+
+func TestLabelSet_Equal(t *testing.T) {
+ tests := []struct {
+ name string
+ set1 LabelSet
+ set2 LabelSet
+ expected bool
+ }{
+ {
+ name: "Both sets empty",
+ set1: NewLabelSet(),
+ set2: NewLabelSet(),
+ expected: true,
+ },
+ {
+ name: "First set empty, second set non-empty",
+ set1: NewLabelSet(),
+ set2: NewLabelSet("label1"),
+ expected: false,
+ },
+ {
+ name: "First set non-empty, second set empty",
+ set1: NewLabelSet("label1"),
+ set2: NewLabelSet(),
+ expected: false,
+ },
+ {
+ name: "Identical sets with single label",
+ set1: NewLabelSet("label1"),
+ set2: NewLabelSet("label1"),
+ expected: true,
+ },
+ {
+ name: "Identical sets with multiple labels",
+ set1: NewLabelSet("label1", "label2", "label3"),
+ set2: NewLabelSet("label3", "label2", "label1"), // Different order
+ expected: true,
+ },
+ {
+ name: "Different sets, same size",
+ set1: NewLabelSet("label1", "label2", "label3"),
+ set2: NewLabelSet("label1", "label2", "label4"),
+ expected: false,
+ },
+ {
+ name: "Different sets, different sizes",
+ set1: NewLabelSet("label1", "label2"),
+ set2: NewLabelSet("label1", "label2", "label3"),
+ expected: false,
+ },
+ {
+ name: "Subset sets",
+ set1: NewLabelSet("label1", "label2"),
+ set2: NewLabelSet("label1", "label2", "label3"),
+ expected: false,
+ },
+ {
+ name: "Disjoint sets",
+ set1: NewLabelSet("label1", "label2"),
+ set2: NewLabelSet("label3", "label4"),
+ expected: false,
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ result := tt.set1.Equal(tt.set2)
+ assert.Equal(t, tt.expected, result, "Equal(%v, %v) should be %v", tt.set1, tt.set2, tt.expected)
+ })
+ }
+}
diff --git a/deployment/address_book_test.go b/deployment/address_book_test.go
index b1fc358f8c1..0c6b228da2e 100644
--- a/deployment/address_book_test.go
+++ b/deployment/address_book_test.go
@@ -5,6 +5,7 @@ import (
"sync"
"testing"
+ "github.com/Masterminds/semver/v3"
"github.com/ethereum/go-ethereum/common"
chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/stretchr/testify/assert"
@@ -243,35 +244,250 @@ func TestAddressBook_ConcurrencyAndDeadlock(t *testing.T) {
wg.Wait()
}
-func TestAddressesContainsBundle(t *testing.T) {
+func TestAddressesContainBundle(t *testing.T) {
+ t.Parallel()
+
+ // Define some TypeAndVersion values
onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0)
onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0)
onRamp120 := NewTypeAndVersion("OnRamp", Version1_2_0)
+
+ // Create one with labels
+ onRamp100WithLabels := NewTypeAndVersion("OnRamp", Version1_0_0)
+ onRamp100WithLabels.Labels.Add("sa")
+ onRamp100WithLabels.Labels.Add("staging")
+
addr1 := common.HexToAddress("0x1").String()
addr2 := common.HexToAddress("0x2").String()
addr3 := common.HexToAddress("0x3").String()
- // More than one instance should error
- _, err := AddressesContainBundle(map[string]TypeAndVersion{
- addr1: onRamp100,
- addr2: onRamp100,
- }, map[TypeAndVersion]struct{}{onRamp100: {}})
- require.Error(t, err)
+ tests := []struct {
+ name string
+ addrs map[string]TypeAndVersion // input address map
+ wantTypes []TypeAndVersion // the “bundle” we want
+ wantErr bool
+ wantErrMsg string
+ wantResult bool // expected boolean return when no error
+ }{
+ {
+ name: "More than one instance => error",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp100,
+ addr2: onRamp100, // duplicate
+ },
+ wantTypes: []TypeAndVersion{onRamp100},
+ wantErr: true,
+ // an example substring check:
+ wantErrMsg: "found more than one instance of contract",
+ },
+ {
+ name: "No instance => result false, no error",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp110,
+ addr2: onRamp110,
+ },
+ wantTypes: []TypeAndVersion{onRamp100},
+ wantErr: false,
+ wantResult: false,
+ },
+ {
+ name: "2 elements => success",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp100,
+ addr2: onRamp110,
+ addr3: onRamp120,
+ },
+ wantTypes: []TypeAndVersion{onRamp100, onRamp110},
+ wantErr: false,
+ wantResult: true,
+ },
+ {
+ name: "Mismatched labels => false",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp100, // no labels
+ },
+ wantTypes: []TypeAndVersion{onRamp100WithLabels},
+ wantErr: false,
+ wantResult: false, // label mismatch => not found
+ },
+ {
+ name: "Exact label match => success",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp100WithLabels,
+ },
+ wantTypes: []TypeAndVersion{onRamp100WithLabels},
+ wantErr: false,
+ wantResult: true,
+ },
+ {
+ name: "Duplicate labeled => error",
+ addrs: map[string]TypeAndVersion{
+ addr1: onRamp100WithLabels,
+ addr2: onRamp100WithLabels, // same type/version/labels => duplicate
+ },
+ wantTypes: []TypeAndVersion{onRamp100WithLabels},
+ wantErr: true,
+ wantErrMsg: "more than one instance of contract",
+ },
+ }
- // No such instances should be false
- exists, err := AddressesContainBundle(map[string]TypeAndVersion{
- addr2: onRamp110,
- addr1: onRamp110,
- }, map[TypeAndVersion]struct{}{onRamp100: {}})
- require.NoError(t, err)
- assert.Equal(t, exists, false)
-
- // 2 elements
- exists, err = AddressesContainBundle(map[string]TypeAndVersion{
- addr1: onRamp100,
- addr2: onRamp110,
- addr3: onRamp120,
- }, map[TypeAndVersion]struct{}{onRamp100: {}, onRamp110: {}})
- require.NoError(t, err)
- assert.Equal(t, exists, true)
+ for _, tt := range tests {
+ tt := tt // capture range variable
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ gotResult, gotErr := AddressesContainBundle(tt.addrs, tt.wantTypes)
+
+ if tt.wantErr {
+ require.Error(t, gotErr, "expected an error but got none")
+ if tt.wantErrMsg != "" {
+ require.Contains(t, gotErr.Error(), tt.wantErrMsg)
+ }
+ return
+ }
+ require.NoError(t, gotErr, "did not expect an error but got one")
+ assert.Equal(t, tt.wantResult, gotResult,
+ "expected result %v but got %v", tt.wantResult, gotResult)
+ })
+ }
+}
+
+func TestTypeAndVersionFromString(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ input string
+ wantErr bool
+ wantType ContractType
+ wantVersion semver.Version
+ wantLabels LabelSet
+ wantTypeAndVersion string
+ }{
+ {
+ name: "valid - no labels",
+ input: "CallProxy 1.0.0",
+ wantErr: false,
+ wantType: "CallProxy",
+ wantVersion: Version1_0_0,
+ wantLabels: NewLabelSet(),
+ wantTypeAndVersion: "CallProxy 1.0.0",
+ },
+ {
+ name: "valid - multiple labels, normal spacing",
+ input: "CallProxy 1.0.0 SA staging",
+ wantErr: false,
+ wantType: "CallProxy",
+ wantVersion: Version1_0_0,
+ wantLabels: NewLabelSet("SA", "staging"),
+ wantTypeAndVersion: "CallProxy 1.0.0 SA staging",
+ },
+ {
+ name: "valid - multiple labels, extra spacing",
+ input: " CallProxy 1.0.0 SA staging ",
+ wantErr: false,
+ wantType: "CallProxy",
+ wantVersion: Version1_0_0,
+ wantLabels: NewLabelSet("SA", "staging"),
+ wantTypeAndVersion: "CallProxy 1.0.0 SA staging",
+ },
+ {
+ name: "invalid - not enough parts",
+ input: "CallProxy",
+ wantErr: true,
+ },
+ {
+ name: "invalid - version not parseable",
+ input: "CallProxy notASemver",
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt // capture range variable
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ gotTV, gotErr := TypeAndVersionFromString(tt.input)
+ if tt.wantErr {
+ require.Error(t, gotErr, "expected error but got none")
+ return
+ }
+ require.NoError(t, gotErr, "did not expect an error but got one")
+
+ // Check ContractType
+ require.Equal(t, tt.wantType, gotTV.Type, "incorrect contract type")
+
+ // Check Version
+ require.Equal(t, tt.wantVersion.String(), gotTV.Version.String(), "incorrect version")
+
+ // Check labels
+ require.Equal(t, tt.wantLabels, gotTV.Labels, "labels mismatch")
+
+ // Check type and version
+ require.Equal(t, tt.wantTypeAndVersion, gotTV.String(), "type and version mismatch")
+ })
+ }
+}
+
+func TestTypeAndVersion_AddLabels(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ initialLabels []string
+ toAdd []string
+ wantContains []string
+ wantLen int
+ }{
+ {
+ name: "add single labels to empty set",
+ initialLabels: nil,
+ toAdd: []string{"foo"},
+ wantContains: []string{"foo"},
+ wantLen: 1,
+ },
+ {
+ name: "add multiple labels to existing set",
+ initialLabels: []string{"alpha"},
+ toAdd: []string{"beta", "gamma"},
+ wantContains: []string{"alpha", "beta", "gamma"},
+ wantLen: 3,
+ },
+ {
+ name: "add duplicate labels",
+ initialLabels: []string{"dup"},
+ toAdd: []string{"dup", "dup", "new"},
+ wantContains: []string{"dup", "new"},
+ wantLen: 2,
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt // capture range variable
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ // Construct a TypeAndVersion with any initial labels
+ tv := TypeAndVersion{
+ Type: "CallProxy",
+ Version: Version1_0_0,
+ Labels: NewLabelSet(tt.initialLabels...),
+ }
+
+ // Call AddLabel for each item in toAdd
+ for _, label := range tt.toAdd {
+ tv.AddLabel(label)
+ }
+
+ // Check final labels length
+ require.Len(t, tv.Labels, tt.wantLen, "labels size mismatch")
+
+ // Check that expected labels is present
+ for _, md := range tt.wantContains {
+ require.True(t, tv.Labels.Contains(md),
+ "expected labels %q was not found in tv.Labels", md)
+ }
+ })
+ }
}
diff --git a/deployment/ccip/changeset/cs_accept_admin_role.go b/deployment/ccip/changeset/cs_accept_admin_role.go
index 68ce58518bf..98c103b5826 100644
--- a/deployment/ccip/changeset/cs_accept_admin_role.go
+++ b/deployment/ccip/changeset/cs_accept_admin_role.go
@@ -34,7 +34,8 @@ func AcceptAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistryCh
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(env, state, c.MCMS)
+
+ deployerGroup := NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("accept admin role for tokens on token admin registries")
for chainSelector, tokenSymbolToPoolInfo := range c.Pools {
chain := env.Chains[chainSelector]
@@ -55,5 +56,5 @@ func AcceptAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistryCh
}
}
- return deployerGroup.Enact("accept admin role for tokens on token admin registries")
+ return deployerGroup.Enact()
}
diff --git a/deployment/ccip/changeset/cs_active_candidate_test.go b/deployment/ccip/changeset/cs_active_candidate_test.go
index a3a0505b950..d0882a078c7 100644
--- a/deployment/ccip/changeset/cs_active_candidate_test.go
+++ b/deployment/ccip/changeset/cs_active_candidate_test.go
@@ -76,7 +76,7 @@ func Test_ActiveCandidate(t *testing.T) {
Config: changeset.UpdateFeeQuoterDestsConfig{
UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{
source: {
- dest: changeset.DefaultFeeQuoterDestChainConfig(),
+ dest: changeset.DefaultFeeQuoterDestChainConfig(true),
},
},
},
@@ -207,7 +207,10 @@ func Test_ActiveCandidate(t *testing.T) {
// NOTE: this is technically not a new chain, but needed for validation.
OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{
dest: changeset.DeriveCCIPOCRParams(
- changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)),
+ changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel,
+ tokenConfig.GetTokenInfo(logger.TestLogger(t),
+ state.Chains[dest].LinkToken.Address(),
+ state.Chains[dest].Weth9.Address())),
),
},
PluginType: types.PluginTypeCCIPCommit,
diff --git a/deployment/ccip/changeset/cs_ccip_home.go b/deployment/ccip/changeset/cs_ccip_home.go
index 67e41f08024..088d36887ee 100644
--- a/deployment/ccip/changeset/cs_ccip_home.go
+++ b/deployment/ccip/changeset/cs_ccip_home.go
@@ -31,7 +31,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
+ capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
)
var (
@@ -303,13 +303,8 @@ func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map
if err := deployment.IsValidChainSelector(chainSelector); err != nil {
return nil, fmt.Errorf("don chain selector invalid: %w", err)
}
- chainState, exists := state.Chains[chainSelector]
- if !exists {
- return nil, fmt.Errorf("chain %d does not exist", chainSelector)
- }
- if chainState.OffRamp == nil {
- // should not be possible, but a defensive check.
- return nil, errors.New("OffRamp contract does not exist")
+ if err := state.ValidateOffRamp(chainSelector); err != nil {
+ return nil, err
}
donID, err := internal.DonIDForChain(
@@ -456,16 +451,14 @@ func (p SetCandidatePluginInfo) Validate(state CCIPOnChainState, homeChain uint6
return errors.New("PluginType must be set to either CCIPCommit or CCIPExec")
}
for chainSelector, params := range p.OCRConfigPerRemoteChainSelector {
- _, ok := state.Chains[chainSelector]
- if !ok {
+ if _, exists := state.SupportedChains()[chainSelector]; !exists {
return fmt.Errorf("chain %d does not exist in state", chainSelector)
}
if err := deployment.IsValidChainSelector(chainSelector); err != nil {
return fmt.Errorf("don chain selector invalid: %w", err)
}
- if state.Chains[chainSelector].OffRamp == nil {
- // should not be possible, but a defensive check.
- return fmt.Errorf("OffRamp contract does not exist on don chain selector %d", chainSelector)
+ if err := state.ValidateOffRamp(chainSelector); err != nil {
+ return err
}
if p.PluginType == types.PluginTypeCCIPCommit && params.CommitOffChainConfig == nil {
return errors.New("commit off-chain config must be set")
@@ -619,12 +612,15 @@ func AddDonAndSetCandidateChangeset(
txOpts = deployment.SimTransactOpts()
}
var donOps []mcms.Operation
-
for chainSelector, params := range cfg.PluginInfo.OCRConfigPerRemoteChainSelector {
+ offRampAddress, err := state.GetOffRampAddress(chainSelector)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome(
e.OCRSecrets,
- state.Chains[chainSelector].OffRamp,
- e.Chains[chainSelector],
+ offRampAddress,
+ chainSelector,
nodes.NonBootstraps(),
state.Chains[cfg.HomeChainSelector].RMNHome.Address(),
params.OCRParameters,
@@ -808,10 +804,14 @@ func SetCandidateChangeset(
for _, plugin := range cfg.PluginInfo {
pluginInfos = append(pluginInfos, plugin.String())
for chainSelector, params := range plugin.OCRConfigPerRemoteChainSelector {
+ offRampAddress, err := state.GetOffRampAddress(chainSelector)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome(
e.OCRSecrets,
- state.Chains[chainSelector].OffRamp,
- e.Chains[chainSelector],
+ offRampAddress,
+ chainSelector,
nodes.NonBootstraps(),
state.Chains[cfg.HomeChainSelector].RMNHome.Address(),
params.OCRParameters,
diff --git a/deployment/ccip/changeset/cs_ccip_home_test.go b/deployment/ccip/changeset/cs_ccip_home_test.go
index feeefae2fff..dcd6fe9f6b6 100644
--- a/deployment/ccip/changeset/cs_ccip_home_test.go
+++ b/deployment/ccip/changeset/cs_ccip_home_test.go
@@ -77,8 +77,8 @@ func TestInvalidOCR3Params(t *testing.T) {
params.OCRParameters.DeltaRound = params.OCRParameters.DeltaProgress + time.Duration(1)
_, err = internal.BuildOCR3ConfigForCCIPHome(
e.Env.OCRSecrets,
- state.Chains[chain1].OffRamp,
- e.Env.Chains[chain1],
+ state.Chains[chain1].OffRamp.Address().Bytes(),
+ chain1,
nodes.NonBootstraps(),
state.Chains[e.HomeChainSel].RMNHome.Address(),
params.OCRParameters,
@@ -264,7 +264,11 @@ func Test_SetCandidate(t *testing.T) {
{
OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{
dest: changeset.DeriveCCIPOCRParams(
- changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)),
+ changeset.WithDefaultCommitOffChainConfig(
+ tenv.FeedChainSel,
+ tokenConfig.GetTokenInfo(logger.TestLogger(t),
+ state.Chains[dest].LinkToken.Address(),
+ state.Chains[dest].Weth9.Address())),
),
},
PluginType: types.PluginTypeCCIPCommit,
@@ -377,7 +381,11 @@ func Test_RevokeCandidate(t *testing.T) {
{
OCRConfigPerRemoteChainSelector: map[uint64]changeset.CCIPOCRParams{
dest: changeset.DeriveCCIPOCRParams(
- changeset.WithDefaultCommitOffChainConfig(tenv.FeedChainSel, tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9)),
+ changeset.WithDefaultCommitOffChainConfig(
+ tenv.FeedChainSel,
+ tokenConfig.GetTokenInfo(logger.TestLogger(t),
+ state.Chains[dest].LinkToken.Address(),
+ state.Chains[dest].Weth9.Address())),
),
},
PluginType: types.PluginTypeCCIPCommit,
diff --git a/deployment/ccip/changeset/cs_chain_contracts.go b/deployment/ccip/changeset/cs_chain_contracts.go
index 201f724eea5..7c2968ff0d1 100644
--- a/deployment/ccip/changeset/cs_chain_contracts.go
+++ b/deployment/ccip/changeset/cs_chain_contracts.go
@@ -14,6 +14,7 @@ import (
"github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
+ chain_selectors "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
@@ -32,13 +33,17 @@ import (
)
var (
- _ deployment.ChangeSet[UpdateOnRampDestsConfig] = UpdateOnRampsDestsChangeset
- _ deployment.ChangeSet[UpdateOffRampSourcesConfig] = UpdateOffRampSourcesChangeset
- _ deployment.ChangeSet[UpdateRouterRampsConfig] = UpdateRouterRampsChangeset
- _ deployment.ChangeSet[UpdateFeeQuoterDestsConfig] = UpdateFeeQuoterDestsChangeset
- _ deployment.ChangeSet[SetOCR3OffRampConfig] = SetOCR3OffRampChangeset
- _ deployment.ChangeSet[UpdateFeeQuoterPricesConfig] = UpdateFeeQuoterPricesChangeset
- _ deployment.ChangeSet[UpdateNonceManagerConfig] = UpdateNonceManagersChangeset
+ _ deployment.ChangeSet[UpdateOnRampDestsConfig] = UpdateOnRampsDestsChangeset
+ _ deployment.ChangeSet[UpdateOnRampDynamicConfig] = UpdateOnRampDynamicConfigChangeset
+ _ deployment.ChangeSet[UpdateOnRampAllowListConfig] = UpdateOnRampAllowListChangeset
+ _ deployment.ChangeSet[WithdrawOnRampFeeTokensConfig] = WithdrawOnRampFeeTokensChangeset
+ _ deployment.ChangeSet[UpdateOffRampSourcesConfig] = UpdateOffRampSourcesChangeset
+ _ deployment.ChangeSet[UpdateRouterRampsConfig] = UpdateRouterRampsChangeset
+ _ deployment.ChangeSet[UpdateFeeQuoterDestsConfig] = UpdateFeeQuoterDestsChangeset
+ _ deployment.ChangeSet[SetOCR3OffRampConfig] = SetOCR3OffRampChangeset
+ _ deployment.ChangeSet[UpdateDynamicConfigOffRampConfig] = UpdateDynamicConfigOffRampChangeset
+ _ deployment.ChangeSet[UpdateFeeQuoterPricesConfig] = UpdateFeeQuoterPricesChangeset
+ _ deployment.ChangeSet[UpdateNonceManagerConfig] = UpdateNonceManagersChangeset
)
type UpdateNonceManagerConfig struct {
@@ -162,12 +167,12 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag
if cfg.MCMS == nil {
if authTx != nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], authTx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, nonce_manager.NonceManagerABI)
}
}
if prevRampsTx != nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], prevRampsTx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, nonce_manager.NonceManagerABI)
}
}
} else {
@@ -216,20 +221,21 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag
}}, nil
}
+type OnRampDestinationUpdate struct {
+ IsEnabled bool // If false, disables the destination by setting router to 0x0.
+ TestRouter bool // Flag for safety only allow specifying either router or testRouter.
+ AllowListEnabled bool
+}
+
type UpdateOnRampDestsConfig struct {
// UpdatesByChain is a mapping of source -> dest -> update.
UpdatesByChain map[uint64]map[uint64]OnRampDestinationUpdate
+
// Disallow mixing MCMS/non-MCMS per chain for simplicity.
// (can still be achieved by calling this function multiple times)
MCMS *MCMSConfig
}
-type OnRampDestinationUpdate struct {
- IsEnabled bool // If false, disables the destination by setting router to 0x0.
- TestRouter bool // Flag for safety only allow specifying either router or testRouter.
- AllowListEnabled bool
-}
-
func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error {
state, err := LoadOnchainState(e)
if err != nil {
@@ -237,6 +243,9 @@ func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error {
}
supportedChains := state.SupportedChains()
for chainSel, updates := range cfg.UpdatesByChain {
+ if err := ValidateChain(e, state, chainSel, cfg.MCMS != nil); err != nil {
+ return err
+ }
chainState, ok := state.Chains[chainSel]
if !ok {
return fmt.Errorf("chain %d not found in onchain state", chainSel)
@@ -253,16 +262,15 @@ func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error {
if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.OnRamp); err != nil {
return err
}
-
+ sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()})
+ if err != nil {
+ return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err)
+ }
for destination := range updates {
// Destination cannot be an unknown destination.
if _, ok := supportedChains[destination]; !ok {
return fmt.Errorf("destination chain %d is not a supported %s", destination, chainState.OnRamp.Address())
}
- sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()})
- if err != nil {
- return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err)
- }
if destination == sc.ChainSelector {
return errors.New("cannot update onramp destination to the same chain")
}
@@ -315,7 +323,7 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, onramp.OnRampABI)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -335,7 +343,6 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests
if cfg.MCMS == nil {
return deployment.ChangesetOutput{}, nil
}
-
p, err := proposalutils.BuildProposalFromBatches(
timelocks,
proposers,
@@ -351,6 +358,361 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests
}}, nil
}
+type OnRampDynamicConfigUpdate struct {
+ MessageInterceptor common.Address
+ FeeAggregator common.Address
+ AllowlistAdmin common.Address
+}
+
+type UpdateOnRampDynamicConfig struct {
+ // UpdatesByChain is a mapping of source -> update.
+ UpdatesByChain map[uint64]OnRampDynamicConfigUpdate
+ // Disallow mixing MCMS/non-MCMS per chain for simplicity.
+ // (can still be achieved by calling this function multiple times)
+ MCMS *MCMSConfig
+}
+
+func (cfg UpdateOnRampDynamicConfig) Validate(e deployment.Environment, state CCIPOnChainState) error {
+ for chainSel, config := range cfg.UpdatesByChain {
+ if err := ValidateChain(e, state, chainSel, cfg.MCMS != nil); err != nil {
+ return err
+ }
+ if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, state.Chains[chainSel].Timelock.Address(), state.Chains[chainSel].OnRamp); err != nil {
+ return err
+ }
+ if state.Chains[chainSel].FeeQuoter == nil {
+ return fmt.Errorf("FeeQuoter is not on state of chain %d", chainSel)
+ }
+ if config.FeeAggregator == (common.Address{}) {
+ return fmt.Errorf("FeeAggregator is not specified for chain %d", chainSel)
+ }
+ }
+ return nil
+}
+
+func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRampDynamicConfig) (deployment.ChangesetOutput, error) {
+ state, err := LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if err := cfg.Validate(e, state); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ var batches []timelock.BatchChainOperation
+ timelocks := make(map[uint64]common.Address)
+ proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig)
+ for chainSel, update := range cfg.UpdatesByChain {
+ txOps := e.Chains[chainSel].DeployerKey
+ if cfg.MCMS != nil {
+ txOps = deployment.SimTransactOpts()
+ }
+ onRamp := state.Chains[chainSel].OnRamp
+ dynamicConfig, err := onRamp.GetDynamicConfig(nil)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ // Do not update dynamic config if it is already in desired state
+ if dynamicConfig.FeeQuoter == state.Chains[chainSel].FeeQuoter.Address() &&
+ dynamicConfig.MessageInterceptor == update.MessageInterceptor &&
+ dynamicConfig.FeeAggregator == update.FeeAggregator &&
+ dynamicConfig.AllowlistAdmin == update.AllowlistAdmin {
+ continue
+ }
+ tx, err := onRamp.SetDynamicConfig(txOps, onramp.OnRampDynamicConfig{
+ FeeQuoter: state.Chains[chainSel].FeeQuoter.Address(),
+ ReentrancyGuardEntered: false,
+ MessageInterceptor: update.MessageInterceptor,
+ FeeAggregator: update.FeeAggregator,
+ AllowlistAdmin: update.AllowlistAdmin,
+ })
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if cfg.MCMS == nil {
+ if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, onramp.OnRampABI)
+ }
+ } else {
+ batches = append(batches, timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(chainSel),
+ Batch: []mcms.Operation{
+ {
+ To: onRamp.Address(),
+ Data: tx.Data(),
+ Value: big.NewInt(0),
+ },
+ },
+ })
+ timelocks[chainSel] = state.Chains[chainSel].Timelock.Address()
+ proposers[chainSel] = state.Chains[chainSel].ProposerMcm
+ }
+ }
+ if cfg.MCMS == nil {
+ return deployment.ChangesetOutput{}, nil
+ }
+ proposal, err := proposalutils.BuildProposalFromBatches(
+ timelocks, proposers, batches,
+ "update onramp dynamic config",
+ cfg.MCMS.MinDelay)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ return deployment.ChangesetOutput{
+ Proposals: []timelock.MCMSWithTimelockProposal{*proposal},
+ }, nil
+}
+
+type OnRampAllowListUpdate struct {
+ AllowListEnabled bool
+ AddedAllowlistedSenders []common.Address
+ RemovedAllowlistedSenders []common.Address
+}
+
+type UpdateOnRampAllowListConfig struct {
+ // UpdatesByChain is a mapping of source -> dest -> update.
+ UpdatesByChain map[uint64]map[uint64]OnRampAllowListUpdate
+ // Disallow mixing MCMS/non-MCMS per chain for simplicity.
+ // (can still be achieved by calling this function multiple times)
+ MCMS *MCMSConfig
+}
+
+func (cfg UpdateOnRampAllowListConfig) Validate(env deployment.Environment) error {
+ state, err := LoadOnchainState(env)
+ if err != nil {
+ return fmt.Errorf("failed to load onchain state: %w", err)
+ }
+ for srcSel, updates := range cfg.UpdatesByChain {
+ if err := ValidateChain(env, state, srcSel, cfg.MCMS != nil); err != nil {
+ return err
+ }
+ onRamp := state.Chains[srcSel].OnRamp
+ if onRamp == nil {
+ return fmt.Errorf("missing onRamp on %d", srcSel)
+ }
+ config, err := onRamp.GetDynamicConfig(nil)
+ if err != nil {
+ return err
+ }
+ owner, err := onRamp.Owner(nil)
+ if err != nil {
+ return fmt.Errorf("failed to get owner: %w", err)
+ }
+ var signer common.Address
+ if cfg.MCMS == nil {
+ signer = env.Chains[srcSel].DeployerKey.From
+ if signer != config.AllowlistAdmin && signer != owner {
+ return fmt.Errorf("deployer key is not onramp's %s owner nor allowlist admin", onRamp.Address())
+ }
+ } else {
+ signer = state.Chains[srcSel].Timelock.Address()
+ if signer != config.AllowlistAdmin && signer != owner {
+ return fmt.Errorf("timelock is not onramp's %s owner nor allowlist admin", onRamp.Address())
+ }
+ }
+ for destSel, update := range updates {
+ if err := ValidateChain(env, state, srcSel, false); err != nil {
+ return err
+ }
+ if len(update.AddedAllowlistedSenders) > 0 && !update.AllowListEnabled {
+ return fmt.Errorf("can't allowlist senders with disabled allowlist for src=%d, dest=%d", srcSel, destSel)
+ }
+ for _, sender := range update.AddedAllowlistedSenders {
+ if sender == (common.Address{}) {
+ return fmt.Errorf("can't allowlist 0-address sender for src=%d, dest=%d", srcSel, destSel)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAllowListConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ onchain, err := LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ var batches []timelock.BatchChainOperation
+ timelocks := make(map[uint64]common.Address)
+ proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig)
+ for srcSel, updates := range cfg.UpdatesByChain {
+ txOps := e.Chains[srcSel].DeployerKey
+ if cfg.MCMS != nil {
+ txOps = deployment.SimTransactOpts()
+ }
+ onRamp := onchain.Chains[srcSel].OnRamp
+ args := make([]onramp.OnRampAllowlistConfigArgs, len(updates))
+ for destSel, update := range updates {
+ allowedSendersResp, err := onRamp.GetAllowedSendersList(nil, destSel)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if allowedSendersResp.IsEnabled == update.AllowListEnabled {
+ desiredState := make(map[common.Address]bool)
+ for _, address := range update.AddedAllowlistedSenders {
+ desiredState[address] = true
+ }
+ for _, address := range update.RemovedAllowlistedSenders {
+ desiredState[address] = false
+ }
+ needUpdate := false
+ for _, allowedSender := range allowedSendersResp.ConfiguredAddresses {
+ if !desiredState[allowedSender] {
+ needUpdate = true
+ }
+ }
+ if !needUpdate {
+ continue
+ }
+ }
+ args = append(args, onramp.OnRampAllowlistConfigArgs{
+ DestChainSelector: destSel,
+ AllowlistEnabled: update.AllowListEnabled,
+ AddedAllowlistedSenders: update.AddedAllowlistedSenders,
+ RemovedAllowlistedSenders: update.RemovedAllowlistedSenders,
+ })
+ }
+ if len(args) == 0 {
+ continue
+ }
+ tx, err := onRamp.ApplyAllowlistUpdates(txOps, args)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if cfg.MCMS == nil {
+ if _, err := deployment.ConfirmIfNoError(e.Chains[srcSel], tx, err); err != nil {
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, onramp.OnRampABI)
+ }
+ } else {
+ batches = append(batches, timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(srcSel),
+ Batch: []mcms.Operation{
+ {
+ To: onRamp.Address(),
+ Data: tx.Data(),
+ Value: big.NewInt(0),
+ },
+ },
+ })
+ timelocks[srcSel] = onchain.Chains[srcSel].Timelock.Address()
+ proposers[srcSel] = onchain.Chains[srcSel].ProposerMcm
+ }
+ }
+ if cfg.MCMS == nil {
+ return deployment.ChangesetOutput{}, nil
+ }
+ proposal, err := proposalutils.BuildProposalFromBatches(
+ timelocks,
+ proposers,
+ batches,
+ "update onramp allowlist",
+ cfg.MCMS.MinDelay,
+ )
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ return deployment.ChangesetOutput{
+ Proposals: []timelock.MCMSWithTimelockProposal{*proposal},
+ }, nil
+}
+
+type WithdrawOnRampFeeTokensConfig struct {
+ FeeTokensByChain map[uint64][]common.Address
+ MCMS *MCMSConfig
+}
+
+func (cfg WithdrawOnRampFeeTokensConfig) Validate(e deployment.Environment, state CCIPOnChainState) error {
+ for chainSel, feeTokens := range cfg.FeeTokensByChain {
+ if err := ValidateChain(e, state, chainSel, cfg.MCMS != nil); err != nil {
+ return err
+ }
+ if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, state.Chains[chainSel].Timelock.Address(), state.Chains[chainSel].OnRamp); err != nil {
+ return err
+ }
+ feeQuoter := state.Chains[chainSel].FeeQuoter
+ if feeQuoter == nil {
+ return fmt.Errorf("no fee quoter for chain %d", chainSel)
+ }
+ onchainFeeTokens, err := feeQuoter.GetFeeTokens(nil)
+ if len(onchainFeeTokens) == 0 {
+ return fmt.Errorf("no fee tokens configured on fee quoter %s for chain %d", feeQuoter.Address().Hex(), chainSel)
+ }
+ if err != nil {
+ return err
+ }
+ for _, feeToken := range feeTokens {
+ found := false
+ for _, onchainFeeToken := range onchainFeeTokens {
+ if onchainFeeToken == feeToken {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("unknown fee token address=%s on chain=%d", feeToken.Hex(), chainSel)
+ }
+ }
+ }
+ return nil
+}
+
+func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRampFeeTokensConfig) (deployment.ChangesetOutput, error) {
+ state, err := LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if err := cfg.Validate(e, state); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ var batches []timelock.BatchChainOperation
+ timelocks := make(map[uint64]common.Address)
+ proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig)
+ for chainSel, feeTokens := range cfg.FeeTokensByChain {
+ txOps := e.Chains[chainSel].DeployerKey
+ onRamp := state.Chains[chainSel].OnRamp
+ tx, err := onRamp.WithdrawFeeTokens(txOps, feeTokens)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if cfg.MCMS == nil {
+ if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, onramp.OnRampABI)
+ }
+ } else {
+ batches = append(batches, timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(chainSel),
+ Batch: []mcms.Operation{
+ {
+ To: onRamp.Address(),
+ Data: tx.Data(),
+ Value: big.NewInt(0),
+ },
+ },
+ })
+ timelocks[chainSel] = state.Chains[chainSel].Timelock.Address()
+ proposers[chainSel] = state.Chains[chainSel].ProposerMcm
+ }
+ }
+ if cfg.MCMS == nil {
+ return deployment.ChangesetOutput{}, nil
+ }
+ proposal, err := proposalutils.BuildProposalFromBatches(
+ timelocks,
+ proposers,
+ batches,
+ "withdraw onramp fee tokens",
+ cfg.MCMS.MinDelay,
+ )
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ return deployment.ChangesetOutput{
+ Proposals: []timelock.MCMSWithTimelockProposal{*proposal},
+ }, nil
+}
+
type UpdateFeeQuoterPricesConfig struct {
PricesByChain map[uint64]FeeQuoterPriceUpdatePerSource // source -> PriceDetails
MCMS *MCMSConfig
@@ -427,7 +789,7 @@ func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error
if price == nil {
return fmt.Errorf("gas price for chain %d is nil", chainSel)
}
- if _, ok := state.Chains[dest]; !ok {
+ if _, ok := state.SupportedChains()[dest]; !ok {
return fmt.Errorf("dest chain %d not found in onchain state for chain %d", dest, chainSel)
}
}
@@ -476,7 +838,8 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
- return deployment.ChangesetOutput{}, fmt.Errorf("error confirming transaction for chain %s: %w", e.Chains[chainSel].String(), err)
+ decodedErr := deployment.DecodedErrFromABIIfDataErr(err, fee_quoter.FeeQuoterABI)
+ return deployment.ChangesetOutput{}, fmt.Errorf("error confirming transaction for chain %s: %w", e.Chains[chainSel].String(), decodedErr)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -592,7 +955,7 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, fee_quoter.FeeQuoterABI)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -628,6 +991,11 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter
}}, nil
}
+type OffRampSourceUpdate struct {
+ IsEnabled bool // If false, disables the source by setting router to 0x0.
+ TestRouter bool // Flag for safety only allow specifying either router or testRouter.
+}
+
type UpdateOffRampSourcesConfig struct {
// UpdatesByChain is a mapping from dest chain -> source chain -> source chain
// update on the dest chain offramp.
@@ -635,16 +1003,7 @@ type UpdateOffRampSourcesConfig struct {
MCMS *MCMSConfig
}
-type OffRampSourceUpdate struct {
- IsEnabled bool // If false, disables the source by setting router to 0x0.
- TestRouter bool // Flag for safety only allow specifying either router or testRouter.
-}
-
-func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment) error {
- state, err := LoadOnchainState(e)
- if err != nil {
- return err
- }
+func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment, state CCIPOnChainState) error {
supportedChains := state.SupportedChains()
for chainSel, updates := range cfg.UpdatesByChain {
chainState, ok := state.Chains[chainSel]
@@ -686,11 +1045,11 @@ func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment) error {
// UpdateOffRampSourcesChangeset updates the offramp sources for each offramp.
func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSourcesConfig) (deployment.ChangesetOutput, error) {
- if err := cfg.Validate(e); err != nil {
+ state, err := LoadOnchainState(e)
+ if err != nil {
return deployment.ChangesetOutput{}, err
}
- s, err := LoadOnchainState(e)
- if err != nil {
+ if err := cfg.Validate(e, state); err != nil {
return deployment.ChangesetOutput{}, err
}
var batches []timelock.BatchChainOperation
@@ -702,18 +1061,16 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo
if cfg.MCMS != nil {
txOpts = deployment.SimTransactOpts()
}
- offRamp := s.Chains[chainSel].OffRamp
+ offRamp := state.Chains[chainSel].OffRamp
var args []offramp.OffRampSourceChainConfigArgs
for source, update := range updates {
router := common.HexToAddress("0x0")
- if update.IsEnabled {
- if update.TestRouter {
- router = s.Chains[chainSel].TestRouter.Address()
- } else {
- router = s.Chains[chainSel].Router.Address()
- }
+ if update.TestRouter {
+ router = state.Chains[chainSel].TestRouter.Address()
+ } else {
+ router = state.Chains[chainSel].Router.Address()
}
- onRamp := s.Chains[source].OnRamp
+ onRamp := state.Chains[source].OnRamp
args = append(args, offramp.OffRampSourceChainConfigArgs{
SourceChainSelector: source,
Router: router,
@@ -727,7 +1084,7 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, offramp.OffRampABI)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -740,8 +1097,8 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo
},
},
})
- timelocks[chainSel] = s.Chains[chainSel].Timelock.Address()
- proposers[chainSel] = s.Chains[chainSel].ProposerMcm
+ timelocks[chainSel] = state.Chains[chainSel].Timelock.Address()
+ proposers[chainSel] = state.Chains[chainSel].ProposerMcm
}
}
if cfg.MCMS == nil {
@@ -763,6 +1120,11 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo
}}, nil
}
+type RouterUpdates struct {
+ OffRampUpdates map[uint64]bool
+ OnRampUpdates map[uint64]bool
+}
+
type UpdateRouterRampsConfig struct {
// TestRouter means the updates will be applied to the test router
// on all chains. Disallow mixing test router/non-test router per chain for simplicity.
@@ -771,18 +1133,12 @@ type UpdateRouterRampsConfig struct {
MCMS *MCMSConfig
}
-type RouterUpdates struct {
- OffRampUpdates map[uint64]bool
- OnRampUpdates map[uint64]bool
-}
-
-func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment) error {
- state, err := LoadOnchainState(e)
- if err != nil {
- return err
- }
+func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state CCIPOnChainState) error {
supportedChains := state.SupportedChains()
for chainSel, update := range cfg.UpdatesByChain {
+ if err := ValidateChain(e, state, chainSel, cfg.MCMS != nil); err != nil {
+ return err
+ }
chainState, ok := state.Chains[chainSel]
if !ok {
return fmt.Errorf("chain %d not found in onchain state", chainSel)
@@ -829,9 +1185,8 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment) error {
if destination == chainSel {
return fmt.Errorf("cannot update onRamp dest to the same chain %d", destination)
}
- destChain := state.Chains[destination]
- if destChain.OffRamp == nil {
- return fmt.Errorf("missing offramp for dest %d", destination)
+ if err := state.ValidateOffRamp(destination); err != nil {
+ return err
}
}
}
@@ -846,11 +1201,11 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment) error {
// on all chains to support the new chain through the test router first. Once tested,
// Enable the new destination on the real router.
func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsConfig) (deployment.ChangesetOutput, error) {
- if err := cfg.Validate(e); err != nil {
+ state, err := LoadOnchainState(e)
+ if err != nil {
return deployment.ChangesetOutput{}, err
}
- s, err := LoadOnchainState(e)
- if err != nil {
+ if err := cfg.Validate(e, state); err != nil {
return deployment.ChangesetOutput{}, err
}
var batches []timelock.BatchChainOperation
@@ -862,14 +1217,14 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC
if cfg.MCMS != nil {
txOpts = deployment.SimTransactOpts()
}
- routerC := s.Chains[chainSel].Router
+ routerC := state.Chains[chainSel].Router
if cfg.TestRouter {
- routerC = s.Chains[chainSel].TestRouter
+ routerC = state.Chains[chainSel].TestRouter
}
// Note if we add distinct offramps per source to the state,
// we'll need to add support here for looking them up.
// For now its simple, all sources use the same offramp.
- offRamp := s.Chains[chainSel].OffRamp
+ offRamp := state.Chains[chainSel].OffRamp
var removes, adds []router.RouterOffRamp
for source, enabled := range update.OffRampUpdates {
if enabled {
@@ -885,7 +1240,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC
}
}
// Ditto here, only one onramp expected until 1.7.
- onRamp := s.Chains[chainSel].OnRamp
+ onRamp := state.Chains[chainSel].OnRamp
var onRampUpdates []router.RouterOnRamp
for dest, enabled := range update.OnRampUpdates {
if enabled {
@@ -906,7 +1261,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, router.RouterABI)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -919,8 +1274,8 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC
},
},
})
- timelocks[chainSel] = s.Chains[chainSel].Timelock.Address()
- proposers[chainSel] = s.Chains[chainSel].ProposerMcm
+ timelocks[chainSel] = state.Chains[chainSel].Timelock.Address()
+ proposers[chainSel] = state.Chains[chainSel].ProposerMcm
}
}
if cfg.MCMS == nil {
@@ -949,26 +1304,51 @@ type SetOCR3OffRampConfig struct {
MCMS *MCMSConfig
}
-func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error {
- state, err := LoadOnchainState(e)
- if err != nil {
- return err
- }
+func (c SetOCR3OffRampConfig) Validate(e deployment.Environment, state CCIPOnChainState) error {
if _, ok := state.Chains[c.HomeChainSel]; !ok {
return fmt.Errorf("home chain %d not found in onchain state", c.HomeChainSel)
}
+ if err := ValidateChain(e, state, c.HomeChainSel, c.MCMS != nil); err != nil {
+ return err
+ }
if c.CCIPHomeConfigType != globals.ConfigTypeActive &&
c.CCIPHomeConfigType != globals.ConfigTypeCandidate {
return fmt.Errorf("invalid CCIPHomeConfigType should be either %s or %s", globals.ConfigTypeActive, globals.ConfigTypeCandidate)
}
for _, remote := range c.RemoteChainSels {
- chainState, ok := state.Chains[remote]
+ if err := c.validateRemoteChain(&e, &state, remote); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (c SetOCR3OffRampConfig) validateRemoteChain(e *deployment.Environment, state *CCIPOnChainState, chainSelector uint64) error {
+ family, err := chain_selectors.GetSelectorFamily(chainSelector)
+ if err != nil {
+ return err
+ }
+ switch family {
+ case chain_selectors.FamilySolana:
+ chainState, ok := state.SolChains[chainSelector]
if !ok {
- return fmt.Errorf("remote chain %d not found in onchain state", remote)
+ return fmt.Errorf("remote chain %d not found in onchain state", chainSelector)
}
- if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[remote].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil {
+
+ // TODO: introduce interface when MCMS is ready
+ if err := commoncs.ValidateOwnershipSolana(e.GetContext(), c.MCMS != nil, e.SolChains[chainSelector].DeployerKey.PublicKey(), chainState.Timelock, chainState.Router); err != nil {
return err
}
+ case chain_selectors.FamilyEVM:
+ chainState, ok := state.Chains[chainSelector]
+ if !ok {
+ return fmt.Errorf("remote chain %d not found in onchain state", chainSelector)
+ }
+ if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[chainSelector].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("unsupported chain family %s", family)
}
return nil
}
@@ -980,13 +1360,13 @@ func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error {
// Multichain is especially helpful for NOP rotations where we have
// to touch all the chain to change signers.
func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) {
- if err := cfg.Validate(e); err != nil {
- return deployment.ChangesetOutput{}, err
- }
state, err := LoadOnchainState(e)
if err != nil {
return deployment.ChangesetOutput{}, err
}
+ if err := cfg.Validate(e, state); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
var batches []timelock.BatchChainOperation
timelocks := make(map[uint64]common.Address)
proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig)
@@ -995,6 +1375,9 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig)
state.Chains[cfg.HomeChainSel].CapabilityRegistry,
state.Chains[cfg.HomeChainSel].CCIPHome,
remote)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
args, err := internal.BuildSetOCR3ConfigArgs(
donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote, cfg.CCIPHomeConfigType)
if err != nil {
@@ -1019,7 +1402,7 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig)
}
if cfg.MCMS == nil {
if _, err := deployment.ConfirmIfNoError(e.Chains[remote], tx, err); err != nil {
- return deployment.ChangesetOutput{}, err
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, offramp.OffRampABI)
}
} else {
batches = append(batches, timelock.BatchChainOperation{
@@ -1055,6 +1438,121 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig)
}}, nil
}
+type UpdateDynamicConfigOffRampConfig struct {
+ Updates map[uint64]OffRampParams
+ MCMS *MCMSConfig
+}
+
+func (cfg UpdateDynamicConfigOffRampConfig) Validate(e deployment.Environment) error {
+ state, err := LoadOnchainState(e)
+ if err != nil {
+ return err
+ }
+ for chainSel, params := range cfg.Updates {
+ if deployment.IsValidChainSelector(chainSel) != nil {
+ return fmt.Errorf("invalid chain selector %d", chainSel)
+ }
+ if _, ok := state.Chains[chainSel]; !ok {
+ return fmt.Errorf("chain %d not found in onchain state", chainSel)
+ }
+ if state.Chains[chainSel].OffRamp == nil {
+ return fmt.Errorf("missing offramp for chain %d", chainSel)
+ }
+ if state.Chains[chainSel].FeeQuoter == nil {
+ return fmt.Errorf("missing fee quoter for chain %d", chainSel)
+ }
+ if state.Chains[chainSel].Timelock == nil {
+ return fmt.Errorf("missing timelock for chain %d", chainSel)
+ }
+ if params.GasForCallExactCheck > 0 {
+ e.Logger.Infow(
+ "GasForCallExactCheck is set, please note it's a static config and will be ignored for this changeset",
+ "chain", chainSel, "gas", params.GasForCallExactCheck)
+ }
+ if err := commoncs.ValidateOwnership(
+ e.GetContext(),
+ cfg.MCMS != nil,
+ e.Chains[chainSel].DeployerKey.From,
+ state.Chains[chainSel].Timelock.Address(),
+ state.Chains[chainSel].OffRamp,
+ ); err != nil {
+ return err
+ }
+ if err := params.Validate(true); err != nil {
+ return fmt.Errorf("chain %d: %w", chainSel, err)
+ }
+ }
+ return nil
+}
+
+func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDynamicConfigOffRampConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ state, err := LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ var batches []timelock.BatchChainOperation
+ timelocks := make(map[uint64]common.Address)
+ proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig)
+ for chainSel, params := range cfg.Updates {
+ chain := e.Chains[chainSel]
+ txOpts := e.Chains[chainSel].DeployerKey
+ if cfg.MCMS != nil {
+ txOpts = deployment.SimTransactOpts()
+ }
+ offRamp := state.Chains[chainSel].OffRamp
+ dCfg := offramp.OffRampDynamicConfig{
+ FeeQuoter: state.Chains[chainSel].FeeQuoter.Address(),
+ PermissionLessExecutionThresholdSeconds: params.PermissionLessExecutionThresholdSeconds,
+ IsRMNVerificationDisabled: params.IsRMNVerificationDisabled,
+ MessageInterceptor: params.MessageInterceptor,
+ }
+ tx, err := offRamp.SetDynamicConfig(txOpts, dCfg)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ if cfg.MCMS == nil {
+ if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil {
+ return deployment.ChangesetOutput{}, deployment.DecodedErrFromABIIfDataErr(err, offramp.OffRampABI)
+ }
+ e.Logger.Infow("Updated offramp dynamic config", "chain", chain.String(), "config", dCfg)
+ } else {
+ batches = append(batches, timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(chainSel),
+ Batch: []mcms.Operation{
+ {
+ To: offRamp.Address(),
+ Data: tx.Data(),
+ Value: big.NewInt(0),
+ },
+ },
+ })
+ timelocks[chainSel] = state.Chains[chainSel].Timelock.Address()
+ proposers[chainSel] = state.Chains[chainSel].ProposerMcm
+ }
+ }
+ if cfg.MCMS == nil {
+ return deployment.ChangesetOutput{}, nil
+ }
+ p, err := proposalutils.BuildProposalFromBatches(
+ timelocks,
+ proposers,
+ batches,
+ "Update offramp dynamic config",
+ cfg.MCMS.MinDelay,
+ )
+
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ e.Logger.Infow("Proposing offramp dynamic config update", "config", cfg.Updates)
+ return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{
+ *p,
+ }}, nil
+}
+
func isOCR3ConfigSetOnOffRamp(
lggr logger.Logger,
chain deployment.Chain,
@@ -1115,7 +1613,9 @@ func isOCR3ConfigSetOnOffRamp(
return true, nil
}
-func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig {
+// DefaultFeeQuoterDestChainConfig returns the default FeeQuoterDestChainConfig
+// with the config enabled/disabled based on the configEnabled flag.
+func DefaultFeeQuoterDestChainConfig(configEnabled bool) fee_quoter.FeeQuoterDestChainConfig {
// https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337
/*
```Solidity
@@ -1125,7 +1625,7 @@ func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig {
*/
evmFamilySelector, _ := hex.DecodeString("2812d52c")
return fee_quoter.FeeQuoterDestChainConfig{
- IsEnabled: true,
+ IsEnabled: configEnabled,
MaxNumberOfTokensPerMsg: 10,
MaxDataBytes: 256,
MaxPerMsgGasLimit: 3_000_000,
diff --git a/deployment/ccip/changeset/cs_chain_contracts_test.go b/deployment/ccip/changeset/cs_chain_contracts_test.go
index 7b7f420e531..c6b6ebb5585 100644
--- a/deployment/ccip/changeset/cs_chain_contracts_test.go
+++ b/deployment/ccip/changeset/cs_chain_contracts_test.go
@@ -1,10 +1,12 @@
package changeset_test
import (
+ "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"
"golang.org/x/exp/maps"
@@ -14,6 +16,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter"
+ "github.com/smartcontractkit/chainlink/v2/evm/utils"
)
func TestUpdateOnRampsDests(t *testing.T) {
@@ -92,6 +95,266 @@ func TestUpdateOnRampsDests(t *testing.T) {
}
}
+func TestUpdateOnRampDynamicConfig(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ mcmsEnabled bool
+ }{
+ {
+ name: "MCMS enabled",
+ mcmsEnabled: true,
+ },
+ {
+ name: "MCMS disabled",
+ mcmsEnabled: false,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := testcontext.Get(t)
+ // Default env just has 2 chains with all contracts
+ // deployed but no lanes.
+ tenv, _ := testhelpers.NewMemoryEnvironment(t)
+ state, err := changeset.LoadOnchainState(tenv.Env)
+ require.NoError(t, err)
+
+ allChains := maps.Keys(tenv.Env.Chains)
+ source := allChains[0]
+ dest := allChains[1]
+
+ if tc.mcmsEnabled {
+ // Transfer ownership to timelock so that we can promote the zero digest later down the line.
+ transferToTimelock(t, tenv, state, source, dest)
+ }
+
+ var mcmsConfig *changeset.MCMSConfig
+ if tc.mcmsEnabled {
+ mcmsConfig = &changeset.MCMSConfig{
+ MinDelay: 0,
+ }
+ }
+ _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampDynamicConfigChangeset),
+ Config: changeset.UpdateOnRampDynamicConfig{
+ UpdatesByChain: map[uint64]changeset.OnRampDynamicConfigUpdate{
+ source: {
+ FeeAggregator: common.HexToAddress("0x1002"),
+ },
+ dest: {
+ FeeAggregator: common.HexToAddress("0x2002"),
+ },
+ },
+ MCMS: mcmsConfig,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ // Assert the onramp configuration is as we expect.
+ sourceCfg, err := state.Chains[source].OnRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx})
+ require.NoError(t, err)
+ require.Equal(t, state.Chains[source].FeeQuoter.Address(), sourceCfg.FeeQuoter)
+ require.Equal(t, common.HexToAddress("0x1002"), sourceCfg.FeeAggregator)
+ destCfg, err := state.Chains[dest].OnRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx})
+ require.NoError(t, err)
+ require.Equal(t, state.Chains[dest].FeeQuoter.Address(), destCfg.FeeQuoter)
+ require.Equal(t, common.HexToAddress("0x2002"), destCfg.FeeAggregator)
+ })
+ }
+}
+
+func TestUpdateOnRampAllowList(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ mcmsEnabled bool
+ }{
+ {
+ name: "MCMS enabled",
+ mcmsEnabled: true,
+ },
+ {
+ name: "MCMS disabled",
+ mcmsEnabled: false,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := testcontext.Get(t)
+ // Default env just has 2 chains with all contracts
+ // deployed but no lanes.
+ tenv, _ := testhelpers.NewMemoryEnvironment(t)
+ state, err := changeset.LoadOnchainState(tenv.Env)
+ require.NoError(t, err)
+
+ allChains := maps.Keys(tenv.Env.Chains)
+ source := allChains[0]
+ dest := allChains[1]
+
+ if tc.mcmsEnabled {
+ // Transfer ownership to timelock so that we can promote the zero digest later down the line.
+ transferToTimelock(t, tenv, state, source, dest)
+ }
+
+ var mcmsConfig *changeset.MCMSConfig
+ if tc.mcmsEnabled {
+ mcmsConfig = &changeset.MCMSConfig{
+ MinDelay: 0,
+ }
+ }
+ _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampAllowListChangeset),
+ Config: changeset.UpdateOnRampAllowListConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset.OnRampAllowListUpdate{
+ source: {
+ dest: {
+ AllowListEnabled: true,
+ AddedAllowlistedSenders: []common.Address{common.HexToAddress("0x1001"), common.HexToAddress("0x1002")},
+ RemovedAllowlistedSenders: []common.Address{common.HexToAddress("0x1002"), common.HexToAddress("0x1003")},
+ },
+ },
+ dest: {
+ source: {
+ AllowListEnabled: true,
+ AddedAllowlistedSenders: []common.Address{common.HexToAddress("0x2001"), common.HexToAddress("0x2002")},
+ RemovedAllowlistedSenders: []common.Address{common.HexToAddress("0x2002"), common.HexToAddress("0x2003")},
+ },
+ },
+ },
+ MCMS: mcmsConfig,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ // Assert the onramp configuration is as we expect.
+ sourceCfg, err := state.Chains[source].OnRamp.GetAllowedSendersList(&bind.CallOpts{Context: ctx}, dest)
+ require.NoError(t, err)
+ require.Contains(t, sourceCfg.ConfiguredAddresses, common.HexToAddress("0x1001"))
+ require.True(t, sourceCfg.IsEnabled)
+ destCfg, err := state.Chains[dest].OnRamp.GetAllowedSendersList(&bind.CallOpts{Context: ctx}, source)
+ require.NoError(t, err)
+ require.Contains(t, destCfg.ConfiguredAddresses, common.HexToAddress("0x2001"))
+ require.True(t, destCfg.IsEnabled)
+ })
+ }
+}
+
+func TestWithdrawOnRampFeeTokens(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ mcmsEnabled bool
+ }{
+ {
+ name: "MCMS enabled",
+ mcmsEnabled: true,
+ },
+ {
+ name: "MCMS disabled",
+ mcmsEnabled: false,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := testcontext.Get(t)
+ // Default env just has 2 chains with all contracts
+ // deployed but no lanes.
+ tenv, _ := testhelpers.NewMemoryEnvironment(t)
+ state, err := changeset.LoadOnchainState(tenv.Env)
+ require.NoError(t, err)
+
+ allChains := maps.Keys(tenv.Env.Chains)
+ source := allChains[0]
+ dest := allChains[1]
+
+ require.NotNil(t, state.Chains[source].ProposerMcm)
+ require.NotNil(t, state.Chains[dest].ProposerMcm)
+
+ if tc.mcmsEnabled {
+ // Transfer ownership to timelock so that we can promote the zero digest later down the line.
+ transferToTimelock(t, tenv, state, source, dest)
+ }
+
+ var mcmsConfig *changeset.MCMSConfig
+ if tc.mcmsEnabled {
+ mcmsConfig = &changeset.MCMSConfig{
+ MinDelay: 0,
+ }
+ }
+
+ linkToken := state.Chains[source].LinkToken
+ require.NotNil(t, linkToken)
+ weth9 := state.Chains[source].Weth9
+ require.NotNil(t, weth9)
+
+ // mint some Link and deposit Weth9 to onramp on source chain
+ tokenAmount := big.NewInt(100)
+ onRamp := state.Chains[source].OnRamp
+ config, err := onRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx})
+ require.NoError(t, err)
+ feeAgggregator := config.FeeAggregator
+ deployer := tenv.Env.Chains[source].DeployerKey
+
+ // LINK
+ tx, err := linkToken.GrantMintRole(deployer, feeAgggregator)
+ require.NoError(t, err)
+ _, err = tenv.Env.Chains[source].Confirm(tx)
+ require.NoError(t, err)
+ tx, err = linkToken.Mint(deployer, onRamp.Address(), tokenAmount)
+ require.NoError(t, err)
+ _, err = tenv.Env.Chains[source].Confirm(tx)
+ require.NoError(t, err)
+
+ // WETH9
+ txOpts := *tenv.Env.Chains[source].DeployerKey
+ txOpts.Value = tokenAmount
+ tx, err = weth9.Deposit(&txOpts)
+ require.NoError(t, err)
+ _, err = tenv.Env.Chains[source].Confirm(tx)
+ require.NoError(t, err)
+ tx, err = weth9.Transfer(deployer, onRamp.Address(), tokenAmount)
+ require.NoError(t, err)
+ _, err = tenv.Env.Chains[source].Confirm(tx)
+ require.NoError(t, err)
+
+ // check init balances
+ aggregatorInitLinks, err := linkToken.BalanceOf(&bind.CallOpts{Context: ctx}, feeAgggregator)
+ require.NoError(t, err)
+ require.Equal(t, int64(0), aggregatorInitLinks.Int64())
+ aggregatorInitWeth, err := weth9.BalanceOf(&bind.CallOpts{Context: ctx}, feeAgggregator)
+ require.NoError(t, err)
+ require.Equal(t, int64(0), aggregatorInitWeth.Int64())
+
+ onRampInitLinks, err := linkToken.BalanceOf(&bind.CallOpts{Context: ctx}, onRamp.Address())
+ require.NoError(t, err)
+ require.Equal(t, tokenAmount, onRampInitLinks)
+ onRampInitWeth, err := weth9.BalanceOf(&bind.CallOpts{Context: ctx}, onRamp.Address())
+ require.NoError(t, err)
+ require.Equal(t, tokenAmount, onRampInitWeth)
+
+ _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.WithdrawOnRampFeeTokensChangeset),
+ Config: changeset.WithdrawOnRampFeeTokensConfig{
+ FeeTokensByChain: map[uint64][]common.Address{
+ source: {linkToken.Address(), weth9.Address()},
+ dest: {state.Chains[dest].LinkToken.Address(), state.Chains[dest].Weth9.Address()},
+ },
+ MCMS: mcmsConfig,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ // Assert that feeAggregator receives all fee tokens from OnRamp
+ aggregatorLinks, err := linkToken.BalanceOf(&bind.CallOpts{Context: ctx}, feeAgggregator)
+ require.NoError(t, err)
+ assert.Equal(t, tokenAmount, aggregatorLinks)
+ aggregatorWeth, err := weth9.BalanceOf(&bind.CallOpts{Context: ctx}, feeAgggregator)
+ require.NoError(t, err)
+ assert.Equal(t, tokenAmount, aggregatorWeth)
+ })
+ }
+}
+
func TestUpdateOffRampsSources(t *testing.T) {
for _, tc := range []struct {
name string
@@ -198,8 +461,8 @@ func TestUpdateFQDests(t *testing.T) {
}
}
- fqCfg1 := changeset.DefaultFeeQuoterDestChainConfig()
- fqCfg2 := changeset.DefaultFeeQuoterDestChainConfig()
+ fqCfg1 := changeset.DefaultFeeQuoterDestChainConfig(true)
+ fqCfg2 := changeset.DefaultFeeQuoterDestChainConfig(true)
fqCfg2.DestGasOverhead = 1000
_, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{
{
@@ -307,6 +570,68 @@ func TestUpdateRouterRamps(t *testing.T) {
}
}
+func TestUpdateDynamicConfigOffRampChangeset(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ mcmsEnabled bool
+ }{
+ {
+ name: "MCMS enabled",
+ mcmsEnabled: true,
+ },
+ {
+ name: "MCMS disabled",
+ mcmsEnabled: false,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ tenv, _ := testhelpers.NewMemoryEnvironment(t)
+ state, err := changeset.LoadOnchainState(tenv.Env)
+ require.NoError(t, err)
+
+ allChains := maps.Keys(tenv.Env.Chains)
+ source := allChains[0]
+ dest := allChains[1]
+
+ if tc.mcmsEnabled {
+ // Transfer ownership to timelock so that we can promote the zero digest later down the line.
+ transferToTimelock(t, tenv, state, source, dest)
+ }
+
+ var mcmsConfig *changeset.MCMSConfig
+ if tc.mcmsEnabled {
+ mcmsConfig = &changeset.MCMSConfig{
+ MinDelay: 0,
+ }
+ }
+ msgInterceptor := utils.RandomAddress()
+ _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.UpdateDynamicConfigOffRampChangeset),
+ Config: changeset.UpdateDynamicConfigOffRampConfig{
+ Updates: map[uint64]changeset.OffRampParams{
+ source: {
+ PermissionLessExecutionThresholdSeconds: uint32(2 * 60 * 60),
+ IsRMNVerificationDisabled: false,
+ MessageInterceptor: msgInterceptor,
+ },
+ },
+ MCMS: mcmsConfig,
+ },
+ },
+ })
+ require.NoError(t, err)
+ // Assert the nonce manager configuration is as we expect.
+ actualConfig, err := state.Chains[source].OffRamp.GetDynamicConfig(nil)
+ require.NoError(t, err)
+ require.Equal(t, uint32(2*60*60), actualConfig.PermissionLessExecutionThresholdSeconds)
+ require.False(t, actualConfig.IsRMNVerificationDisabled)
+ require.Equal(t, msgInterceptor, actualConfig.MessageInterceptor)
+ require.Equal(t, state.Chains[source].FeeQuoter.Address(), actualConfig.FeeQuoter)
+ })
+ }
+}
+
func TestUpdateNonceManagersCS(t *testing.T) {
for _, tc := range []struct {
name string
diff --git a/deployment/ccip/changeset/cs_configure_token_pools.go b/deployment/ccip/changeset/cs_configure_token_pools.go
index bbddfaa43c2..bdf4072030a 100644
--- a/deployment/ccip/changeset/cs_configure_token_pools.go
+++ b/deployment/ccip/changeset/cs_configure_token_pools.go
@@ -173,7 +173,8 @@ func ConfigureTokenPoolContractsChangeset(env deployment.Environment, c Configur
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(env, state, c.MCMS)
+
+ deployerGroup := NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext(fmt.Sprintf("configure %s token pools", c.TokenSymbol))
for chainSelector := range c.PoolUpdates {
chain := env.Chains[chainSelector]
@@ -188,7 +189,7 @@ func ConfigureTokenPoolContractsChangeset(env deployment.Environment, c Configur
}
}
- return deployerGroup.Enact(fmt.Sprintf("configure %s token pools", c.TokenSymbol))
+ return deployerGroup.Enact()
}
// configureTokenPool creates all transactions required to configure the desired token pool on a chain,
diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go
index b8de97dbf9c..fea65fa30a5 100644
--- a/deployment/ccip/changeset/cs_deploy_chain.go
+++ b/deployment/ccip/changeset/cs_deploy_chain.go
@@ -12,12 +12,14 @@ import (
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
"golang.org/x/sync/errgroup"
- "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"
-
solBinary "github.com/gagliardetto/binary"
solRpc "github.com/gagliardetto/solana-go/rpc"
chainsel "github.com/smartcontractkit/chain-selectors"
+ solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"
+ solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
+ solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"
+
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
@@ -58,6 +60,7 @@ func DeployChainContractsChangeset(env deployment.Environment, c DeployChainCont
return deployment.ChangesetOutput{
Proposals: []timelock.MCMSWithTimelockProposal{},
AddressBook: newAddresses,
+ Jobs: nil,
JobSpecs: nil,
}, nil
}
@@ -91,7 +94,7 @@ func (c ChainContractParams) Validate() error {
if err := c.FeeQuoterParams.Validate(); err != nil {
return fmt.Errorf("invalid FeeQuoterParams: %w", err)
}
- if err := c.OffRampParams.Validate(); err != nil {
+ if err := c.OffRampParams.Validate(false); err != nil {
return fmt.Errorf("invalid OffRampParams: %w", err)
}
return nil
@@ -145,10 +148,11 @@ type OffRampParams struct {
GasForCallExactCheck uint16
PermissionLessExecutionThresholdSeconds uint32
IsRMNVerificationDisabled bool
+ MessageInterceptor common.Address
}
-func (c OffRampParams) Validate() error {
- if c.GasForCallExactCheck == 0 {
+func (c OffRampParams) Validate(ignoreGasForCallExactCheck bool) error {
+ if !ignoreGasForCallExactCheck && c.GasForCallExactCheck == 0 {
return errors.New("GasForCallExactCheck is 0")
}
if c.PermissionLessExecutionThresholdSeconds == 0 {
@@ -213,29 +217,23 @@ func deployChainContractsForChains(
ab deployment.AddressBook,
homeChainSel uint64,
contractParamsPerChain map[uint64]ChainContractParams) error {
- existingEVMState, err := LoadOnchainState(e)
+ existingState, err := LoadOnchainState(e)
if err != nil {
e.Logger.Errorw("Failed to load existing onchain state", "err", err)
return err
}
- err = validateHomeChainState(e, homeChainSel, existingEVMState)
+ err = validateHomeChainState(e, homeChainSel, existingState)
if err != nil {
return err
}
- rmnHome := existingEVMState.Chains[homeChainSel].RMNHome
-
- existingSolState, err := LoadOnchainStateSolana(e)
- if err != nil {
- e.Logger.Errorw("Failed to load existing onchain solanastate", "err", err)
- return err
- }
+ rmnHome := existingState.Chains[homeChainSel].RMNHome
deployGrp := errgroup.Group{}
for chainSel, contractParams := range contractParamsPerChain {
- if _, exists := existingEVMState.SupportedChains()[chainSel]; !exists {
+ if _, exists := existingState.SupportedChains()[chainSel]; !exists {
return fmt.Errorf("chain %d not supported", chainSel)
}
// already validated family
@@ -243,25 +241,24 @@ func deployChainContractsForChains(
var deployFn func() error
switch family {
case chainsel.FamilyEVM:
- staticLinkExists := existingEVMState.Chains[chainSel].StaticLinkToken != nil
- linkExists := existingEVMState.Chains[chainSel].LinkToken != nil
- weth9Exists := existingEVMState.Chains[chainSel].Weth9 != nil
+ staticLinkExists := existingState.Chains[chainSel].StaticLinkToken != nil
+ linkExists := existingState.Chains[chainSel].LinkToken != nil
+ weth9Exists := existingState.Chains[chainSel].Weth9 != nil
feeTokensAreValid := weth9Exists && (linkExists != staticLinkExists)
if !feeTokensAreValid {
return fmt.Errorf("fee tokens not valid for chain %d, staticLinkExists: %t, linkExists: %t, weth9Exists: %t", chainSel, staticLinkExists, linkExists, weth9Exists)
}
chain := e.Chains[chainSel]
- if existingEVMState.Chains[chainSel].LinkToken == nil || existingEVMState.Chains[chainSel].Weth9 == nil {
- return fmt.Errorf("fee tokens not found for chain %d", chainSel)
- }
deployFn = func() error { return deployChainContractsEVM(e, chain, ab, rmnHome, contractParams) }
case chainsel.FamilySolana:
chain := e.SolChains[chainSel]
- if existingSolState.SolChains[chainSel].LinkToken.IsZero() {
+ if existingState.SolChains[chainSel].LinkToken.IsZero() {
return fmt.Errorf("fee tokens not found for chain %d", chainSel)
}
deployFn = func() error { return deployChainContractsSolana(e, chain, ab) }
+ default:
+ return fmt.Errorf("unsupported chain family for chain %d", chainSel)
}
deployGrp.Go(func() error {
err := deployFn()
@@ -271,7 +268,6 @@ func deployChainContractsForChains(
}
return nil
})
-
}
if err := deployGrp.Wait(); err != nil {
e.Logger.Errorw("Failed to deploy chain contracts", "err", err)
@@ -501,6 +497,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a
FeeQuoter: feeQuoterContract.Address(),
PermissionLessExecutionThresholdSeconds: contractParams.OffRampParams.PermissionLessExecutionThresholdSeconds,
IsRMNVerificationDisabled: contractParams.OffRampParams.IsRMNVerificationDisabled,
+ MessageInterceptor: contractParams.OffRampParams.MessageInterceptor,
},
[]offramp.OffRampSourceChainConfigArgs{},
)
@@ -538,6 +535,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a
return nil
}
+// TODO: move everything below to solana file
func solRouterProgramData(e deployment.Environment, chain deployment.SolChain, ccipRouterProgram solana.PublicKey) (struct {
DataType uint32
Address solana.PublicKey
@@ -560,15 +558,43 @@ func solRouterProgramData(e deployment.Environment, chain deployment.SolChain, c
return programData, nil
}
-func checkRouterInitialized(e deployment.Environment, chain deployment.SolChain, ccipRouterProgram solana.PublicKey) (bool, error) {
- routerConfigPDA := GetRouterConfigPDA(ccipRouterProgram)
- routerConfigInfo, err := chain.Client.GetAccountInfoWithOpts(e.GetContext(), routerConfigPDA, &solRpc.GetAccountInfoOpts{
- Commitment: solRpc.CommitmentConfirmed,
- })
+func initializeRouter(e deployment.Environment, chain deployment.SolChain, ccipRouterProgram solana.PublicKey, linkTokenAddress solana.PublicKey) error {
+ programData, err := solRouterProgramData(e, chain, ccipRouterProgram)
+ if err != nil {
+ return fmt.Errorf("failed to get solana router program data: %w", err)
+ }
+ // addressing errcheck in the next PR
+ routerConfigPDA, _, _ := solState.FindConfigPDA(ccipRouterProgram)
+ routerStatePDA, _, _ := solState.FindStatePDA(ccipRouterProgram)
+ externalExecutionConfigPDA, _, _ := solState.FindExternalExecutionConfigPDA(ccipRouterProgram)
+ externalTokenPoolsSignerPDA, _, _ := solState.FindExternalTokenPoolsSignerPDA(ccipRouterProgram)
+
+ instruction, err := solRouter.NewInitializeInstruction(
+ chain.Selector, // chain selector
+ deployment.SolDefaultGasLimit, // default gas limit
+ true, // allow out of order execution
+ EnableExecutionAfter, // period to wait before allowing manual execution
+ solana.PublicKey{}, // fee aggregator (TODO: changeset to set the fee aggregator)
+ linkTokenAddress, // link token mint
+ deployment.SolDefaultMaxFeeJuelsPerMsg, // max fee juels per msg
+ routerConfigPDA,
+ routerStatePDA,
+ chain.DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ccipRouterProgram,
+ programData.Address,
+ externalExecutionConfigPDA,
+ externalTokenPoolsSignerPDA,
+ ).ValidateAndBuild()
+
if err != nil {
- return false, nil
+ return fmt.Errorf("failed to build instruction: %w", err)
+ }
+ if err := chain.Confirm([]solana.Instruction{instruction}); err != nil {
+ return fmt.Errorf("failed to confirm instructions: %w", err)
}
- return routerConfigInfo != nil && len(routerConfigInfo.Value.Data.GetBinary()) > 0, nil
+ e.Logger.Infow("Initialized router", "chain", chain.String())
+ return nil
}
func deployChainContractsSolana(
@@ -583,20 +609,22 @@ func deployChainContractsSolana(
}
chainState, chainExists := state.SolChains[chain.Selector]
if !chainExists {
- return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String())
+ return fmt.Errorf("chain %s not found in existing state, deploy the link token first", chain.String())
+ }
+ if chainState.LinkToken.IsZero() {
+ return fmt.Errorf("failed to get link token address for chain %s", chain.String())
}
- linkTokenContract := chainState.LinkToken
- e.Logger.Infow("link token", "addr", linkTokenContract.String())
+ // ROUTER DEPLOY AND INITIALIZE
var ccipRouterProgram solana.PublicKey
- if chainState.SolCcipRouter.IsZero() {
+ if chainState.Router.IsZero() {
// deploy router
programID, err := chain.DeployProgram(e.Logger, "ccip_router")
if err != nil {
return fmt.Errorf("failed to deploy program: %w", err)
}
- tv := deployment.NewTypeAndVersion("SolCcipRouter", deployment.Version1_0_0)
+ tv := deployment.NewTypeAndVersion(Router, deployment.Version1_0_0)
e.Logger.Infow("Deployed contract", "Contract", tv.String(), "addr", programID, "chain", chain.String())
ccipRouterProgram = solana.MustPublicKeyFromBase58(programID)
@@ -605,53 +633,80 @@ func deployChainContractsSolana(
return fmt.Errorf("failed to save address: %w", err)
}
} else {
- e.Logger.Infow("Using existing router", "addr", chainState.SolCcipRouter.String())
- ccipRouterProgram = chainState.SolCcipRouter
+ e.Logger.Infow("Using existing router", "addr", chainState.Router.String())
+ ccipRouterProgram = chainState.Router
}
- ccip_router.SetProgramID(ccipRouterProgram)
+ solRouter.SetProgramID(ccipRouterProgram)
// check if solana router is initialised
- initialized, err := checkRouterInitialized(e, chain, ccipRouterProgram)
+ var routerConfigAccount solRouter.Config
+ // addressing errcheck in the next PR
+ routerConfigPDA, _, _ := solState.FindConfigPDA(ccipRouterProgram)
+ err = chain.GetAccountDataBorshInto(e.GetContext(), routerConfigPDA, &routerConfigAccount)
if err != nil {
- return err
- }
- if initialized {
+ if err2 := initializeRouter(e, chain, ccipRouterProgram, chainState.LinkToken); err2 != nil {
+ return err2
+ }
+ } else {
e.Logger.Infow("Router already initialized, skipping initialization", "chain", chain.String())
- return nil
- }
-
- programData, err := solRouterProgramData(e, chain, ccipRouterProgram)
- if err != nil {
- return fmt.Errorf("failed to get solana router program data: %w", err)
}
-
- instruction, err := ccip_router.NewInitializeInstruction(
- chain.Selector, // chain selector
- EnableExecutionAfter, // period to wait before allowing manual execution
- solana.PublicKey{},
- solana.PublicKey{},
- solBinary.Uint128{Lo: 300000000, Hi: 0, Endianness: nil},
- GetRouterConfigPDA(ccipRouterProgram),
- GetRouterStatePDA(ccipRouterProgram),
- chain.DeployerKey.PublicKey(),
- solana.SystemProgramID,
- ccipRouterProgram,
- programData.Address,
- GetExternalExecutionConfigPDA(ccipRouterProgram),
- GetExternalTokenPoolsSignerPDA(ccipRouterProgram),
- ).ValidateAndBuild()
-
- if err != nil {
- return fmt.Errorf("failed to build instruction: %w", err)
- }
- err = chain.Confirm([]solana.Instruction{instruction})
-
- if err != nil {
- return fmt.Errorf("failed to confirm instructions: %w", err)
+
+ var tokenPoolProgram solana.PublicKey
+ if chainState.TokenPool.IsZero() {
+ // TODO: there should be two token pools deployed one of each type (lock/burn)
+ // separate token pools are not ready yet
+ programID, err := chain.DeployProgram(e.Logger, "token_pool")
+ if err != nil {
+ return fmt.Errorf("failed to deploy program: %w", err)
+ }
+ tv := deployment.NewTypeAndVersion(TokenPool, deployment.Version1_0_0)
+ e.Logger.Infow("Deployed contract", "Contract", tv.String(), "addr", programID, "chain", chain.String())
+ tokenPoolProgram = solana.MustPublicKeyFromBase58(programID)
+ err = ab.Save(chain.Selector, programID, tv)
+ if err != nil {
+ return fmt.Errorf("failed to save address: %w", err)
+ }
+ } else {
+ e.Logger.Infow("Using existing token pool", "addr", chainState.TokenPool.String())
+ tokenPoolProgram = chainState.TokenPool
+ }
+
+ // initialize this last with every address we need
+ if chainState.AddressLookupTable.IsZero() {
+ // addressing errcheck in the next PR
+ routerConfigPDA, _, _ := solState.FindConfigPDA(ccipRouterProgram)
+ routerStatePDA, _, _ := solState.FindStatePDA(ccipRouterProgram)
+ externalExecutionConfigPDA, _, _ := solState.FindExternalExecutionConfigPDA(ccipRouterProgram)
+ externalTokenPoolsSignerPDA, _, _ := solState.FindExternalTokenPoolsSignerPDA(ccipRouterProgram)
+ table, err := solCommonUtil.SetupLookupTable(
+ e.GetContext(),
+ chain.Client,
+ *chain.DeployerKey,
+ []solana.PublicKey{
+ // system
+ solana.SystemProgramID,
+ solana.ComputeBudget,
+ solana.SysVarInstructionsPubkey,
+ // router
+ ccipRouterProgram,
+ routerConfigPDA,
+ routerStatePDA,
+ externalExecutionConfigPDA,
+ externalTokenPoolsSignerPDA,
+ // token pools
+ tokenPoolProgram,
+ // token
+ solana.Token2022ProgramID,
+ solana.TokenProgramID,
+ solana.SPLAssociatedTokenAccountProgramID,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to create lookup table: %w", err)
+ }
+ err = ab.Save(chain.Selector, table.String(), deployment.NewTypeAndVersion(AddressLookupTable, deployment.Version1_0_0))
+ if err != nil {
+ return fmt.Errorf("failed to save address: %w", err)
+ }
}
-
- //TODO: deploy token pool contract
- //TODO: log errors
-
return nil
}
diff --git a/deployment/ccip/changeset/cs_deploy_chain_test.go b/deployment/ccip/changeset/cs_deploy_chain_test.go
index 7069cadfb3f..027fa26ca92 100644
--- a/deployment/ccip/changeset/cs_deploy_chain_test.go
+++ b/deployment/ccip/changeset/cs_deploy_chain_test.go
@@ -1,8 +1,6 @@
package changeset_test
import (
- "encoding/json"
- "fmt"
"testing"
"github.com/stretchr/testify/require"
@@ -24,16 +22,10 @@ func TestDeployChainContractsChangeset(t *testing.T) {
e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
Bootstraps: 1,
Chains: 2,
- SolChains: 1,
Nodes: 4,
})
evmSelectors := e.AllChainSelectors()
homeChainSel := evmSelectors[0]
- solChainSelectors := e.AllChainSelectorsSolana()
- testhelpers.SavePreloadedSolAddresses(t, e, solChainSelectors[0])
- selectors := make([]uint64, 0, len(evmSelectors)+len(solChainSelectors))
- selectors = append(selectors, evmSelectors...)
- selectors = append(selectors, solChainSelectors...)
nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)
require.NoError(t, err)
p2pIds := nodes.NonBootstraps().PeerIDs()
@@ -46,18 +38,13 @@ func TestDeployChainContractsChangeset(t *testing.T) {
OffRampParams: changeset.DefaultOffRampParams(),
}
}
- for _, chain := range solChainSelectors {
- contractParams[chain] = changeset.ChainContractParams{
- FeeQuoterParams: changeset.DefaultFeeQuoterParams(),
- OffRampParams: changeset.DefaultOffRampParams(),
- }
- }
prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0)
for _, chain := range e.AllChainSelectors() {
prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{
ChainSelector: chain,
})
}
+
e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset),
@@ -73,7 +60,7 @@ func TestDeployChainContractsChangeset(t *testing.T) {
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
- Config: selectors,
+ Config: evmSelectors,
},
{
Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
@@ -116,28 +103,20 @@ func TestDeployChainContractsChangeset(t *testing.T) {
require.NotNil(t, state.Chains[sel].OffRamp)
require.NotNil(t, state.Chains[sel].OnRamp)
}
-
- solState, err := changeset.LoadOnchainStateSolana(e)
- require.NoError(t, err)
- for _, sel := range solChainSelectors {
- require.NotNil(t, solState.SolChains[sel].LinkToken)
- require.NotNil(t, solState.SolChains[sel].SolCcipRouter)
- }
-
}
func TestDeployCCIPContracts(t *testing.T) {
t.Parallel()
- e, _ := testhelpers.NewMemoryEnvironment(t)
- // Deploy all the CCIP contracts.
- state, err := changeset.LoadOnchainState(e.Env)
- require.NoError(t, err)
- snap, err := state.View(e.Env.AllChainSelectors())
- require.NoError(t, err)
+ testhelpers.DeployCCIPContractsTest(t, 0)
+}
- // 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, "", " ")
+func TestDeployStaticLinkToken(t *testing.T) {
+ t.Parallel()
+ e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithStaticLink())
+ // load onchain state
+ state, err := changeset.LoadOnchainState(e.Env)
require.NoError(t, err)
- fmt.Println(string(b))
+ for _, chain := range e.Env.AllChainSelectors() {
+ require.NotNil(t, state.Chains[chain].StaticLinkToken)
+ }
}
diff --git a/deployment/ccip/changeset/cs_home_chain.go b/deployment/ccip/changeset/cs_home_chain.go
index 9a691a8d8ab..90f4bcd7933 100644
--- a/deployment/ccip/changeset/cs_home_chain.go
+++ b/deployment/ccip/changeset/cs_home_chain.go
@@ -49,6 +49,7 @@ func DeployHomeChainChangeset(env deployment.Environment, cfg DeployHomeChainCon
Proposals: []timelock.MCMSWithTimelockProposal{},
AddressBook: ab,
JobSpecs: nil,
+ Jobs: nil,
}, nil
}
diff --git a/deployment/ccip/changeset/cs_jobspec.go b/deployment/ccip/changeset/cs_jobspec.go
index ffa331021c5..2ed6bd4aa15 100644
--- a/deployment/ccip/changeset/cs_jobspec.go
+++ b/deployment/ccip/changeset/cs_jobspec.go
@@ -6,6 +6,7 @@ import (
"github.com/pelletier/go-toml/v2"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
+
"github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
chainsel "github.com/smartcontractkit/chain-selectors"
@@ -117,6 +118,7 @@ func CCIPCapabilityJobspecChangeset(env deployment.Environment, _ any) (deployme
Proposals: []timelock.MCMSWithTimelockProposal{},
AddressBook: nil,
JobSpecs: nodesToJobSpecs,
+ Jobs: nil,
}, nil
}
diff --git a/deployment/ccip/changeset/cs_jobspec_test.go b/deployment/ccip/changeset/cs_jobspec_test.go
index 11fececb244..8ffa810711d 100644
--- a/deployment/ccip/changeset/cs_jobspec_test.go
+++ b/deployment/ccip/changeset/cs_jobspec_test.go
@@ -21,6 +21,7 @@ func TestJobSpecChangeset(t *testing.T) {
Chains: 1,
Nodes: 4,
})
+ // TODO: Replace this with a changeset which proposes the jobs, and returns job ids.
output, err := changeset.CCIPCapabilityJobspecChangeset(e, nil)
require.NoError(t, err)
require.NotNil(t, output.JobSpecs)
diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go
index da4f59c3eb6..c5b1f12a6fa 100644
--- a/deployment/ccip/changeset/cs_prerequisites.go
+++ b/deployment/ccip/changeset/cs_prerequisites.go
@@ -7,9 +7,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
+ "golang.org/x/sync/errgroup"
+
"github.com/smartcontractkit/chainlink-ccip/pkg/reader"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- "golang.org/x/sync/errgroup"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver"
@@ -23,9 +24,9 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
)
var (
@@ -53,6 +54,7 @@ func DeployPrerequisitesChangeset(env deployment.Environment, cfg DeployPrerequi
Proposals: []timelock.MCMSWithTimelockProposal{},
AddressBook: ab,
JobSpecs: nil,
+ Jobs: nil,
}, nil
}
diff --git a/deployment/ccip/changeset/cs_propose_admin_role.go b/deployment/ccip/changeset/cs_propose_admin_role.go
index b6db1b0611d..231a8e5c4c9 100644
--- a/deployment/ccip/changeset/cs_propose_admin_role.go
+++ b/deployment/ccip/changeset/cs_propose_admin_role.go
@@ -38,7 +38,8 @@ func ProposeAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistryC
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(env, state, c.MCMS)
+
+ deployerGroup := NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("propose admin role for tokens on token admin registries")
for chainSelector, tokenSymbolToPoolInfo := range c.Pools {
chain := env.Chains[chainSelector]
@@ -66,5 +67,5 @@ func ProposeAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistryC
}
}
- return deployerGroup.Enact("propose admin role for tokens on token admin registries")
+ return deployerGroup.Enact()
}
diff --git a/deployment/ccip/changeset/cs_rmn_curse_uncurse.go b/deployment/ccip/changeset/cs_rmn_curse_uncurse.go
index b6125638143..3f382549996 100644
--- a/deployment/ccip/changeset/cs_rmn_curse_uncurse.go
+++ b/deployment/ccip/changeset/cs_rmn_curse_uncurse.go
@@ -219,7 +219,8 @@ func RMNCurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployment
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(e, state, cfg.MCMS)
+
+ deployerGroup := NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to curse RMNs: " + cfg.Reason)
// Generate curse actions
var curseActions []RMNCurseAction
@@ -263,7 +264,7 @@ func RMNCurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployment
}
}
- return deployerGroup.Enact("proposal to curse RMNs: " + cfg.Reason)
+ return deployerGroup.Enact()
}
// RMNUncurseChangeset creates a new changeset for uncursing chains or lanes on RMNRemote contracts.
@@ -289,7 +290,8 @@ func RMNUncurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployme
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(e, state, cfg.MCMS)
+
+ deployerGroup := NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to uncurse RMNs: " + cfg.Reason)
// Generate curse actions
var curseActions []RMNCurseAction
@@ -335,5 +337,5 @@ func RMNUncurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (deployme
}
}
- return deployerGroup.Enact("proposal to uncurse RMNs: %s" + cfg.Reason)
+ return deployerGroup.Enact()
}
diff --git a/deployment/ccip/changeset/cs_set_pool.go b/deployment/ccip/changeset/cs_set_pool.go
index 96661d1fe65..8db2f5dedbc 100644
--- a/deployment/ccip/changeset/cs_set_pool.go
+++ b/deployment/ccip/changeset/cs_set_pool.go
@@ -34,7 +34,8 @@ func SetPoolChangeset(env deployment.Environment, c TokenAdminRegistryChangesetC
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(env, state, c.MCMS)
+
+ deployerGroup := NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("set pool for tokens on token admin registries")
for chainSelector, tokenSymbolToPoolInfo := range c.Pools {
chain := env.Chains[chainSelector]
@@ -55,5 +56,5 @@ func SetPoolChangeset(env deployment.Environment, c TokenAdminRegistryChangesetC
}
}
- return deployerGroup.Enact("set pool for tokens on token admin registries")
+ return deployerGroup.Enact()
}
diff --git a/deployment/ccip/changeset/cs_transfer_admin_role.go b/deployment/ccip/changeset/cs_transfer_admin_role.go
index a5d9269dc0c..141a9cdf1ef 100644
--- a/deployment/ccip/changeset/cs_transfer_admin_role.go
+++ b/deployment/ccip/changeset/cs_transfer_admin_role.go
@@ -39,7 +39,8 @@ func TransferAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistry
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(env, state, c.MCMS)
+
+ deployerGroup := NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("transfer admin role for tokens on token admin registries")
for chainSelector, tokenSymbolToPoolInfo := range c.Pools {
chain := env.Chains[chainSelector]
@@ -60,5 +61,5 @@ func TransferAdminRoleChangeset(env deployment.Environment, c TokenAdminRegistry
}
}
- return deployerGroup.Enact("transfer admin role for tokens on token admin registries")
+ return deployerGroup.Enact()
}
diff --git a/deployment/ccip/changeset/cs_update_rmn_config.go b/deployment/ccip/changeset/cs_update_rmn_config.go
index 07c6333ab76..551e7e564b1 100644
--- a/deployment/ccip/changeset/cs_update_rmn_config.go
+++ b/deployment/ccip/changeset/cs_update_rmn_config.go
@@ -565,7 +565,8 @@ func SetRMNHomeDynamicConfigChangeset(e deployment.Environment, cfg SetRMNHomeDy
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(e, state, cfg.MCMS)
+
+ deployerGroup := NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("set RMNHome dynamic config")
chain, exists := e.Chains[cfg.HomeChainSelector]
if !exists {
@@ -588,7 +589,7 @@ func SetRMNHomeDynamicConfigChangeset(e deployment.Environment, cfg SetRMNHomeDy
return deployment.ChangesetOutput{}, fmt.Errorf("failed to set RMNHome dynamic config for chain %s: %w", chain.String(), err)
}
- return deployerGroup.Enact("Set RMNHome dynamic config")
+ return deployerGroup.Enact()
}
type RevokeCandidateConfig struct {
@@ -635,7 +636,8 @@ func RevokeRMNHomeCandidateConfigChangeset(e deployment.Environment, cfg RevokeC
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
}
- deployerGroup := NewDeployerGroup(e, state, cfg.MCMS)
+
+ deployerGroup := NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("revoke candidate config")
chain, exists := e.Chains[cfg.HomeChainSelector]
if !exists {
@@ -657,7 +659,7 @@ func RevokeRMNHomeCandidateConfigChangeset(e deployment.Environment, cfg RevokeC
return deployment.ChangesetOutput{}, fmt.Errorf("failed to revoke candidate config for chain %s: %w", chain.String(), err)
}
- return deployerGroup.Enact("Revoke candidate config")
+ return deployerGroup.Enact()
}
func SetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (deployment.ChangesetOutput, error) {
diff --git a/deployment/ccip/changeset/deployer_group.go b/deployment/ccip/changeset/deployer_group.go
index a552d6d9f9b..6ebf5ce9658 100644
--- a/deployment/ccip/changeset/deployer_group.go
+++ b/deployment/ccip/changeset/deployer_group.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math/big"
+ "slices"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -23,10 +24,51 @@ type MCMSConfig struct {
}
type DeployerGroup struct {
- e deployment.Environment
- state CCIPOnChainState
- mcmConfig *MCMSConfig
- transactions map[uint64][]*types.Transaction
+ e deployment.Environment
+ state CCIPOnChainState
+ mcmConfig *MCMSConfig
+ deploymentContext *DeploymentContext
+}
+
+type DeploymentContext struct {
+ description string
+ transactions map[uint64][]*types.Transaction
+ previousConfig *DeploymentContext
+}
+
+func NewDeploymentContext(description string) *DeploymentContext {
+ return &DeploymentContext{
+ description: description,
+ transactions: make(map[uint64][]*types.Transaction),
+ previousConfig: nil,
+ }
+}
+
+func (d *DeploymentContext) Fork(description string) *DeploymentContext {
+ return &DeploymentContext{
+ description: description,
+ transactions: make(map[uint64][]*types.Transaction),
+ previousConfig: d,
+ }
+}
+
+type DeployerGroupWithContext interface {
+ WithDeploymentContext(description string) *DeployerGroup
+}
+
+type deployerGroupBuilder struct {
+ e deployment.Environment
+ state CCIPOnChainState
+ mcmConfig *MCMSConfig
+}
+
+func (d *deployerGroupBuilder) WithDeploymentContext(description string) *DeployerGroup {
+ return &DeployerGroup{
+ e: d.e,
+ mcmConfig: d.mcmConfig,
+ state: d.state,
+ deploymentContext: NewDeploymentContext(description),
+ }
}
// DeployerGroup is an abstraction that lets developers write their changeset
@@ -41,12 +83,20 @@ type DeployerGroup struct {
// state.Chains[selector].RMNRemote.Curse()
// # Execute the transaction or create the proposal
// deployerGroup.Enact("Curse RMNRemote")
-func NewDeployerGroup(e deployment.Environment, state CCIPOnChainState, mcmConfig *MCMSConfig) *DeployerGroup {
+func NewDeployerGroup(e deployment.Environment, state CCIPOnChainState, mcmConfig *MCMSConfig) DeployerGroupWithContext {
+ return &deployerGroupBuilder{
+ e: e,
+ mcmConfig: mcmConfig,
+ state: state,
+ }
+}
+
+func (d *DeployerGroup) WithDeploymentContext(description string) *DeployerGroup {
return &DeployerGroup{
- e: e,
- mcmConfig: mcmConfig,
- state: state,
- transactions: make(map[uint64][]*types.Transaction),
+ e: d.e,
+ mcmConfig: d.mcmConfig,
+ state: d.state,
+ deploymentContext: d.deploymentContext.Fork(description),
}
}
@@ -94,77 +144,145 @@ func (d *DeployerGroup) GetDeployer(chain uint64) (*bind.TransactOpts, error) {
startingNonce = new(big.Int).SetUint64(nonce)
}
+ dc := d.deploymentContext
sim.Signer = func(a common.Address, t *types.Transaction) (*types.Transaction, error) {
- // Update the nonce to consider the transactions that have been sent
- sim.Nonce = big.NewInt(0).Add(startingNonce, big.NewInt(int64(len(d.transactions[chain]))+1))
+ txCount, err := d.getTransactionCount(chain)
+ if err != nil {
+ return nil, err
+ }
+
+ currentNonce := big.NewInt(0).Add(startingNonce, txCount)
tx, err := oldSigner(a, t)
if err != nil {
return nil, err
}
- d.transactions[chain] = append(d.transactions[chain], tx)
+ dc.transactions[chain] = append(dc.transactions[chain], tx)
+ // Update the nonce to consider the transactions that have been sent
+ sim.Nonce = big.NewInt(0).Add(currentNonce, big.NewInt(1))
return tx, nil
}
return sim, nil
}
-func (d *DeployerGroup) Enact(deploymentDescription string) (deployment.ChangesetOutput, error) {
+func (d *DeployerGroup) getContextChainInOrder() []*DeploymentContext {
+ contexts := make([]*DeploymentContext, 0)
+ for c := d.deploymentContext; c != nil; c = c.previousConfig {
+ contexts = append(contexts, c)
+ }
+ slices.Reverse(contexts)
+ return contexts
+}
+
+func (d *DeployerGroup) getTransactions() map[uint64][]*types.Transaction {
+ transactions := make(map[uint64][]*types.Transaction)
+ for _, c := range d.getContextChainInOrder() {
+ for k, v := range c.transactions {
+ transactions[k] = append(transactions[k], v...)
+ }
+ }
+ return transactions
+}
+
+func (d *DeployerGroup) getTransactionCount(chain uint64) (*big.Int, error) {
+ txs := d.getTransactions()
+ return big.NewInt(int64(len(txs[chain]))), nil
+}
+
+func (d *DeployerGroup) Enact() (deployment.ChangesetOutput, error) {
if d.mcmConfig != nil {
- return d.enactMcms(deploymentDescription)
+ return d.enactMcms()
}
return d.enactDeployer()
}
-func (d *DeployerGroup) enactMcms(deploymentDescription string) (deployment.ChangesetOutput, error) {
- batches := make([]timelock.BatchChainOperation, 0)
- for selector, txs := range d.transactions {
- mcmOps := make([]mcms.Operation, len(txs))
- for i, tx := range txs {
- mcmOps[i] = mcms.Operation{
- To: *tx.To(),
- Data: tx.Data(),
- Value: tx.Value(),
+func (d *DeployerGroup) enactMcms() (deployment.ChangesetOutput, error) {
+ contexts := d.getContextChainInOrder()
+ proposals := make([]timelock.MCMSWithTimelockProposal, 0)
+ for _, dc := range contexts {
+ batches := make([]timelock.BatchChainOperation, 0)
+ for selector, txs := range dc.transactions {
+ mcmOps := make([]mcms.Operation, len(txs))
+ for i, tx := range txs {
+ mcmOps[i] = mcms.Operation{
+ To: *tx.To(),
+ Data: tx.Data(),
+ Value: tx.Value(),
+ }
}
+ batches = append(batches, timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(selector),
+ Batch: mcmOps,
+ })
+ }
+
+ if len(batches) == 0 {
+ d.e.Logger.Warnf("No batch was produced from deployment context skipping proposal: %s", dc.description)
+ continue
}
- batches = append(batches, timelock.BatchChainOperation{
- ChainIdentifier: mcms.ChainIdentifier(selector),
- Batch: mcmOps,
- })
- }
- timelocksPerChain := BuildTimelockAddressPerChain(d.e, d.state)
+ timelocksPerChain := BuildTimelockAddressPerChain(d.e, d.state)
- proposerMCMSes := BuildProposerPerChain(d.e, d.state)
+ proposerMCMSes := BuildProposerPerChain(d.e, d.state)
- prop, err := proposalutils.BuildProposalFromBatches(
- timelocksPerChain,
- proposerMCMSes,
- batches,
- deploymentDescription,
- d.mcmConfig.MinDelay,
- )
+ prop, err := proposalutils.BuildProposalFromBatches(
+ timelocksPerChain,
+ proposerMCMSes,
+ batches,
+ dc.description,
+ d.mcmConfig.MinDelay,
+ )
- if err != nil {
- return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal %w", err)
+ // Update the proposal metadata to incorporate the startingOpCount
+ // from the previous proposal
+ if len(proposals) > 0 {
+ previousProposal := proposals[len(proposals)-1]
+ for chain, metadata := range previousProposal.ChainMetadata {
+ nextStartingOp := metadata.StartingOpCount + getBatchCountForChain(chain, prop)
+ prop.ChainMetadata[chain] = mcms.ChainMetadata{
+ StartingOpCount: nextStartingOp,
+ MCMAddress: prop.ChainMetadata[chain].MCMAddress,
+ }
+ }
+ }
+
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal %w", err)
+ }
+
+ proposals = append(proposals, *prop)
}
return deployment.ChangesetOutput{
- Proposals: []timelock.MCMSWithTimelockProposal{*prop},
+ Proposals: proposals,
}, nil
}
+func getBatchCountForChain(chain mcms.ChainIdentifier, m *timelock.MCMSWithTimelockProposal) uint64 {
+ batches := make([]timelock.BatchChainOperation, 0)
+ for _, t := range m.Transactions {
+ if t.ChainIdentifier == chain {
+ batches = append(batches, t)
+ }
+ }
+ return uint64(len(batches))
+}
+
func (d *DeployerGroup) enactDeployer() (deployment.ChangesetOutput, error) {
- for selector, txs := range d.transactions {
- for _, tx := range txs {
- err := d.e.Chains[selector].Client.SendTransaction(context.Background(), tx)
- if err != nil {
- return deployment.ChangesetOutput{}, fmt.Errorf("failed to send transaction: %w", err)
- }
+ contexts := d.getContextChainInOrder()
+ for _, c := range contexts {
+ for selector, txs := range c.transactions {
+ for _, tx := range txs {
+ err := d.e.Chains[selector].Client.SendTransaction(context.Background(), tx)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to send transaction: %w", err)
+ }
- _, err = d.e.Chains[selector].Confirm(tx)
- if err != nil {
- return deployment.ChangesetOutput{}, fmt.Errorf("waiting for tx to be mined failed: %w", err)
+ _, err = d.e.Chains[selector].Confirm(tx)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("waiting for tx to be mined failed: %w", err)
+ }
}
}
}
diff --git a/deployment/ccip/changeset/deployer_group_test.go b/deployment/ccip/changeset/deployer_group_test.go
index ba598ec74e8..0f670f0d2f6 100644
--- a/deployment/ccip/changeset/deployer_group_test.go
+++ b/deployment/ccip/changeset/deployer_group_test.go
@@ -1,18 +1,33 @@
package changeset_test
import (
+ "fmt"
"math/big"
"testing"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
+ "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms"
+
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
)
+type mintConfig struct {
+ selectorIndex uint64
+ amount *big.Int
+}
+
+type dummyMultiChainDeployerGroupChangesetConfig struct {
+ address common.Address
+ mints []mintConfig
+ MCMS *changeset.MCMSConfig
+}
+
type dummyDeployerGroupChangesetConfig struct {
selector uint64
address common.Address
@@ -20,6 +35,20 @@ type dummyDeployerGroupChangesetConfig struct {
MCMS *changeset.MCMSConfig
}
+type dummyEmptyBatchChangesetConfig struct {
+ MCMS *changeset.MCMSConfig
+}
+
+func dummyEmptyBatchChangeset(e deployment.Environment, cfg dummyEmptyBatchChangesetConfig) (deployment.ChangesetOutput, error) {
+ state, err := changeset.LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("empty batch")
+ return group.Enact()
+}
+
func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) {
state, err := changeset.LoadOnchainState(e)
if err != nil {
@@ -28,7 +57,7 @@ func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDep
token := state.Chains[cfg.selector].LinkToken
- group := changeset.NewDeployerGroup(e, state, cfg.MCMS)
+ group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role")
deployer, err := group.GetDeployer(cfg.selector)
if err != nil {
return deployment.ChangesetOutput{}, err
@@ -39,7 +68,7 @@ func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDep
return deployment.ChangesetOutput{}, err
}
- return group.Enact("Grant mint role")
+ return group.Enact()
}
func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) {
@@ -50,7 +79,7 @@ func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployer
token := state.Chains[cfg.selector].LinkToken
- group := changeset.NewDeployerGroup(e, state, cfg.MCMS)
+ group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("mint tokens")
deployer, err := group.GetDeployer(cfg.selector)
if err != nil {
return deployment.ChangesetOutput{}, err
@@ -63,7 +92,64 @@ func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployer
}
}
- return group.Enact("Mint tokens")
+ return group.Enact()
+}
+
+func dummyDeployerGroupGrantMintMultiChainChangeset(e deployment.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) {
+ state, err := changeset.LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role")
+ for _, mint := range cfg.mints {
+ selector := e.AllChainSelectors()[mint.selectorIndex]
+ token := state.Chains[selector].LinkToken
+
+ deployer, err := group.GetDeployer(selector)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ _, err = token.GrantMintRole(deployer, deployer.From)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ }
+
+ return group.Enact()
+}
+
+func dummyDeployerGroupMintMultiDeploymentContextChangeset(e deployment.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (deployment.ChangesetOutput, error) {
+ state, err := changeset.LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ var group *changeset.DeployerGroup
+ var deployer *bind.TransactOpts
+
+ for i, mint := range cfg.mints {
+ selector := e.AllChainSelectors()[mint.selectorIndex]
+ token := state.Chains[selector].LinkToken
+
+ if group == nil {
+ group = changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext(fmt.Sprintf("mint tokens %d", i+1))
+ } else {
+ group = group.WithDeploymentContext(fmt.Sprintf("mint tokens %d", i+1))
+ }
+ deployer, err = group.GetDeployer(selector)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ _, err = token.Mint(deployer, cfg.address, mint.amount)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ }
+
+ return group.Enact()
}
type deployerGroupTestCase struct {
@@ -191,3 +277,152 @@ func TestDeployerGroupMCMS(t *testing.T) {
})
}
}
+
+func TestDeployerGroupGenerateMultipleProposals(t *testing.T) {
+ tc := dummyMultiChainDeployerGroupChangesetConfig{
+ address: common.HexToAddress("0x455E5AA18469bC6ccEF49594645666C587A3a71B"),
+ mints: []mintConfig{
+ {
+ selectorIndex: 0,
+ amount: big.NewInt(1),
+ },
+ {
+ selectorIndex: 0,
+ amount: big.NewInt(2),
+ },
+ {
+ selectorIndex: 1,
+ amount: big.NewInt(4),
+ },
+ },
+ MCMS: &changeset.MCMSConfig{
+ MinDelay: 0,
+ },
+ }
+ e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2))
+ state, err := changeset.LoadOnchainState(e.Env)
+ require.NoError(t, err)
+
+ timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state)
+
+ contractsByChain := make(map[uint64][]common.Address)
+ for _, chain := range e.Env.AllChainSelectors() {
+ contractsByChain[chain] = []common.Address{state.Chains[chain].LinkToken.Address()}
+ }
+
+ _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock),
+ Config: commonchangeset.TransferToMCMSWithTimelockConfig{
+ ContractsByChain: contractsByChain,
+ MinDelay: 0,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(dummyDeployerGroupGrantMintMultiChainChangeset),
+ Config: tc,
+ },
+ })
+ require.NoError(t, err)
+
+ cs, err := dummyDeployerGroupMintMultiDeploymentContextChangeset(e.Env, tc)
+ require.NoError(t, err)
+ require.Len(t, cs.Proposals, len(tc.mints))
+ require.Equal(t, "mint tokens 1", cs.Proposals[0].Description)
+ require.Equal(t, "mint tokens 2", cs.Proposals[1].Description)
+ require.Equal(t, "mint tokens 3", cs.Proposals[2].Description)
+ require.Equal(t, uint64(2), cs.Proposals[0].ChainMetadata[mcms.ChainIdentifier(e.Env.AllChainSelectors()[tc.mints[0].selectorIndex])].StartingOpCount)
+ require.Equal(t, uint64(3), cs.Proposals[1].ChainMetadata[mcms.ChainIdentifier(e.Env.AllChainSelectors()[tc.mints[1].selectorIndex])].StartingOpCount)
+ require.Equal(t, uint64(2), cs.Proposals[2].ChainMetadata[mcms.ChainIdentifier(e.Env.AllChainSelectors()[tc.mints[2].selectorIndex])].StartingOpCount)
+}
+
+func TestDeployerGroupMultipleProposalsMCMS(t *testing.T) {
+ cfg := dummyMultiChainDeployerGroupChangesetConfig{
+ address: common.HexToAddress("0x455E5AA18469bC6ccEF49594645666C587A3a71B"),
+ mints: []mintConfig{
+ {
+ selectorIndex: 0,
+ amount: big.NewInt(1),
+ },
+ {
+ selectorIndex: 0,
+ amount: big.NewInt(2),
+ },
+ },
+ MCMS: &changeset.MCMSConfig{
+ MinDelay: 0,
+ },
+ }
+
+ e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2))
+
+ state, err := changeset.LoadOnchainState(e.Env)
+ require.NoError(t, err)
+
+ timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state)
+
+ contractsByChain := make(map[uint64][]common.Address)
+ for _, chain := range e.Env.AllChainSelectors() {
+ contractsByChain[chain] = []common.Address{state.Chains[chain].LinkToken.Address()}
+ }
+
+ _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock),
+ Config: commonchangeset.TransferToMCMSWithTimelockConfig{
+ ContractsByChain: contractsByChain,
+ MinDelay: 0,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(dummyDeployerGroupGrantMintMultiChainChangeset),
+ Config: cfg,
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(dummyDeployerGroupMintMultiDeploymentContextChangeset),
+ Config: cfg,
+ },
+ })
+ require.NoError(t, err)
+
+ state, err = changeset.LoadOnchainState(e.Env)
+ require.NoError(t, err)
+
+ token := state.Chains[e.HomeChainSel].LinkToken
+
+ amount, err := token.BalanceOf(nil, cfg.address)
+ require.NoError(t, err)
+
+ sumOfMints := big.NewInt(0)
+ for _, mint := range cfg.mints {
+ sumOfMints = sumOfMints.Add(sumOfMints, mint.amount)
+ }
+
+ require.Equal(t, sumOfMints, amount)
+}
+
+func TestEmptyBatch(t *testing.T) {
+ e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2))
+
+ cfg := dummyEmptyBatchChangesetConfig{
+ MCMS: &changeset.MCMSConfig{
+ MinDelay: 0,
+ },
+ }
+
+ result, err := dummyEmptyBatchChangeset(e.Env, cfg)
+ require.NoError(t, err)
+ require.Empty(t, result.Proposals)
+}
diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go
index ada04376a36..d25ae916bec 100644
--- a/deployment/ccip/changeset/internal/deploy_home_chain.go
+++ b/deployment/ccip/changeset/internal/deploy_home_chain.go
@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/gagliardetto/solana-go"
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper"
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types"
@@ -17,13 +18,12 @@ import (
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
- types2 "github.com/smartcontractkit/chainlink/deployment/common/types"
+ commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/evm/utils"
-
)
const (
@@ -185,13 +185,73 @@ func BuildSetOCR3ConfigArgs(
return offrampOCR3Configs, nil
}
+// https://github.com/smartcontractkit/chainlink-ccip/blob/bdbfcc588847d70817333487a9883e94c39a332e/chains/solana/gobindings/ccip_router/SetOcrConfig.go#L23
+type MultiOCR3BaseOCRConfigArgsSolana struct {
+ ConfigDigest [32]byte
+ OCRPluginType uint8
+ F uint8
+ IsSignatureVerificationEnabled bool
+ Signers [][20]byte
+ Transmitters []solana.PublicKey
+}
+
+// BuildSetOCR3ConfigArgsSolana builds OCR3 config for Solana chains
+func BuildSetOCR3ConfigArgsSolana(
+ donID uint32,
+ ccipHome *ccip_home.CCIPHome,
+ destSelector uint64,
+) ([]MultiOCR3BaseOCRConfigArgsSolana, error) {
+ ocr3Configs := make([]MultiOCR3BaseOCRConfigArgsSolana, 0)
+ for _, pluginType := range []types.PluginType{types.PluginTypeCCIPCommit, types.PluginTypeCCIPExec} {
+ ocrConfig, err2 := ccipHome.GetAllConfigs(&bind.CallOpts{
+ Context: context.Background(),
+ }, donID, uint8(pluginType))
+ if err2 != nil {
+ return nil, err2
+ }
+
+ // 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 [][20]byte
+ var transmitterAddresses []solana.PublicKey
+ for _, node := range activeConfig.Config.Nodes {
+ var signer [20]uint8
+ if len(node.SignerKey) != 20 {
+ return nil, fmt.Errorf("node signer key not 20 bytes long, got: %d", len(node.SignerKey))
+ }
+ copy(signer[:], node.SignerKey)
+ signerAddresses = append(signerAddresses, signer)
+ // https://smartcontract-it.atlassian.net/browse/NONEVM-1254
+ key, err := solana.PublicKeyFromBase58(string(node.TransmitterKey))
+ if err != nil {
+ return nil, err
+ }
+ transmitterAddresses = append(transmitterAddresses, key)
+ }
+
+ ocr3Configs = append(ocr3Configs, MultiOCR3BaseOCRConfigArgsSolana{
+ ConfigDigest: activeConfig.ConfigDigest,
+ OCRPluginType: uint8(pluginType),
+ F: activeConfig.Config.FRoleDON,
+ IsSignatureVerificationEnabled: pluginType == types.PluginTypeCCIPCommit,
+ Signers: signerAddresses,
+ Transmitters: transmitterAddresses,
+ })
+ }
+ return ocr3Configs, nil
+}
+
func BuildOCR3ConfigForCCIPHome(
ocrSecrets deployment.OCRSecrets,
- offRamp offramp.OffRampInterface,
- dest deployment.Chain,
+ offRampAddress []byte,
+ destSelector uint64,
nodes deployment.Nodes,
rmnHomeAddress common.Address,
- ocrParams types2.OCRParameters,
+ ocrParams commontypes.OCRParameters,
commitOffchainCfg *pluginconfig.CommitOffchainConfig,
execOffchainCfg *pluginconfig.ExecuteOffchainConfig,
) (map[types.PluginType]ccip_home.CCIPHomeOCR3Config, error) {
@@ -201,9 +261,9 @@ func BuildOCR3ConfigForCCIPHome(
var oracles []confighelper.OracleIdentityExtra
for _, node := range nodes {
schedule = append(schedule, 1)
- cfg, exists := node.OCRConfigForChainSelector(dest.Selector)
+ cfg, exists := node.OCRConfigForChainSelector(destSelector)
if !exists {
- return nil, fmt.Errorf("no OCR config for chain %d", dest.Selector)
+ return nil, fmt.Errorf("no OCR config for chain %d", destSelector)
}
oracles = append(oracles, confighelper.OracleIdentityExtra{
OracleIdentity: confighelper.OracleIdentity{
@@ -327,10 +387,10 @@ func BuildOCR3ConfigForCCIPHome(
ocr3Configs[pluginType] = ccip_home.CCIPHomeOCR3Config{
PluginType: uint8(pluginType),
- ChainSelector: dest.Selector,
+ ChainSelector: destSelector,
FRoleDON: configF,
OffchainConfigVersion: offchainConfigVersion,
- OfframpAddress: offRamp.Address().Bytes(),
+ OfframpAddress: offRampAddress,
Nodes: ocrNodes,
OffchainConfig: offchainConfig,
RmnHomeAddress: rmnHomeAddress.Bytes(),
diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go
index f575bc005f2..487b57f8952 100644
--- a/deployment/ccip/changeset/save_existing_test.go
+++ b/deployment/ccip/changeset/save_existing_test.go
@@ -30,27 +30,27 @@ func TestSaveExistingCCIP(t *testing.T) {
cfg := commonchangeset.ExistingContractsConfig{
ExistingContracts: []commonchangeset.Contract{
{
- Address: common.BigToAddress(big.NewInt(1)),
+ Address: common.BigToAddress(big.NewInt(1)).String(),
TypeAndVersion: deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0),
ChainSelector: chain1,
},
{
- Address: common.BigToAddress(big.NewInt(2)),
+ Address: common.BigToAddress(big.NewInt(2)).String(),
TypeAndVersion: deployment.NewTypeAndVersion(changeset.WETH9, deployment.Version1_0_0),
ChainSelector: chain1,
},
{
- Address: common.BigToAddress(big.NewInt(3)),
+ Address: common.BigToAddress(big.NewInt(3)).String(),
TypeAndVersion: deployment.NewTypeAndVersion(changeset.TokenAdminRegistry, deployment.Version1_5_0),
ChainSelector: chain1,
},
{
- Address: common.BigToAddress(big.NewInt(4)),
+ Address: common.BigToAddress(big.NewInt(4)).String(),
TypeAndVersion: deployment.NewTypeAndVersion(changeset.RegistryModule, deployment.Version1_5_0),
ChainSelector: chain2,
},
{
- Address: common.BigToAddress(big.NewInt(5)),
+ Address: common.BigToAddress(big.NewInt(5)).String(),
TypeAndVersion: deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0),
ChainSelector: chain2,
},
diff --git a/deployment/ccip/changeset/solana/cs_chain_contracts.go b/deployment/ccip/changeset/solana/cs_chain_contracts.go
new file mode 100644
index 00000000000..a5a4bfae663
--- /dev/null
+++ b/deployment/ccip/changeset/solana/cs_chain_contracts.go
@@ -0,0 +1,928 @@
+package solana
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strconv"
+
+ "github.com/gagliardetto/solana-go"
+
+ solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"
+ "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/token_pool"
+ solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
+ solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"
+ solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens"
+
+ ata "github.com/gagliardetto/solana-go/programs/associated-token-account"
+
+ chainsel "github.com/smartcontractkit/chain-selectors"
+
+ "github.com/smartcontractkit/chainlink/deployment"
+ cs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal"
+ commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+)
+
+var _ deployment.ChangeSet[AddRemoteChainToSolanaConfig] = AddRemoteChainToSolana
+var _ deployment.ChangeSet[TokenPoolConfig] = AddTokenPool
+var _ deployment.ChangeSet[RemoteChainTokenPoolConfig] = SetupTokenPoolForRemoteChain
+var _ deployment.ChangeSet[cs.SetOCR3OffRampConfig] = SetOCR3ConfigSolana
+var _ deployment.ChangeSet[BillingTokenConfig] = AddBillingToken
+var _ deployment.ChangeSet[BillingTokenForRemoteChainConfig] = AddBillingTokenForRemoteChain
+var _ deployment.ChangeSet[RegisterTokenAdminRegistryConfig] = RegisterTokenAdminRegistry
+var _ deployment.ChangeSet[TransferAdminRoleTokenAdminRegistryConfig] = TransferAdminRoleTokenAdminRegistry
+var _ deployment.ChangeSet[AcceptAdminRoleTokenAdminRegistryConfig] = AcceptAdminRoleTokenAdminRegistry
+
+// GetTokenProgramID returns the program ID for the given token program name
+func GetTokenProgramID(programName string) (solana.PublicKey, error) {
+ tokenPrograms := map[string]solana.PublicKey{
+ deployment.SPLTokens: solana.TokenProgramID, // not used yet
+ deployment.SPL2022Tokens: solana.Token2022ProgramID,
+ }
+
+ programID, ok := tokenPrograms[programName]
+ if !ok {
+ return solana.PublicKey{}, fmt.Errorf("invalid token program: %s. Must be one of: %s, %s", programName, deployment.SPLTokens, deployment.SPL2022Tokens)
+ }
+ return programID, nil
+}
+
+// GetPoolType returns the token pool type constant for the given string
+func GetPoolType(poolType string) (token_pool.PoolType, error) {
+ poolTypes := map[string]token_pool.PoolType{
+ "LockAndRelease": token_pool.LockAndRelease_PoolType,
+ "BurnAndMint": token_pool.BurnAndMint_PoolType,
+ }
+
+ poolTypeConstant, ok := poolTypes[poolType]
+ if !ok {
+ return 0, fmt.Errorf("invalid pool type: %s. Must be one of: LockAndRelease, BurnAndMint", poolType)
+ }
+ return poolTypeConstant, nil
+}
+
+func commonValidation(e deployment.Environment, selector uint64, tokenPubKey solana.PublicKey) error {
+ chain, ok := e.SolChains[selector]
+ if !ok {
+ return fmt.Errorf("chain selector %d not found in environment", selector)
+ }
+ state, err := cs.LoadOnchainState(e)
+ if err != nil {
+ return fmt.Errorf("failed to load onchain state: %w", err)
+ }
+ chainState, chainExists := state.SolChains[selector]
+ if !chainExists {
+ return fmt.Errorf("chain %s not found in existing state, deploy the link token first", chain.String())
+ }
+ if tokenPubKey.Equals(chainState.LinkToken) || tokenPubKey.Equals(chainState.WSOL) {
+ return nil
+ }
+ exists := false
+ for _, token := range chainState.SPL2022Tokens {
+ if token.Equals(tokenPubKey) {
+ exists = true
+ break
+ }
+ }
+ if !exists {
+ return fmt.Errorf("token %s not found in existing state, deploy the token first", tokenPubKey.String())
+ }
+ return nil
+}
+
+func validateRouterConfig(chain deployment.SolChain, chainState cs.SolCCIPChainState) error {
+ if chainState.Router.IsZero() {
+ return fmt.Errorf("router not found in existing state, deploy the router first chain %d", chain.Selector)
+ }
+ // addressing errcheck in the next PR
+ var routerConfigAccount solRouter.Config
+ err := chain.GetAccountDataBorshInto(context.Background(), chainState.RouterConfigPDA, &routerConfigAccount)
+ if err != nil {
+ return fmt.Errorf("router config not found in existing state, initialize the router first %d", chain.Selector)
+ }
+ return nil
+}
+
+// ADD REMOTE CHAIN
+type AddRemoteChainToSolanaConfig struct {
+ // UpdatesByChain is a mapping of SVM chain selector -> remote chain selector -> remote chain config update
+ UpdatesByChain map[uint64]map[uint64]RemoteChainConfigSolana
+ // Disallow mixing MCMS/non-MCMS per chain for simplicity.
+ // (can still be achieved by calling this function multiple times)
+ MCMS *cs.MCMSConfig
+}
+
+// https://github.com/smartcontractkit/chainlink-ccip/blob/771fb9957d818253d833431e7e980669984e1d6a/chains/solana/gobindings/ccip_router/types.go#L1141
+// https://github.com/smartcontractkit/chainlink-ccip/blob/771fb9957d818253d833431e7e980669984e1d6a/chains/solana/contracts/tests/ccip/ccip_router_test.go#L130
+// We are not using solRouter.SourceChainConfig because that would involve the user
+// converting the onRamp address into [2][64]byte{} which is not intuitive.
+// The solRouter.DestChainConfig on the other hand has a lot of fields and most of them are uint
+// So we are using that directly instead of copying over the fields here to reduce
+// overhead cost if that type is bumped in chainlink-ccip
+type RemoteChainConfigSolana struct {
+ // source
+ EnabledAsSource bool
+ // destination
+ DestinationConfig solRouter.DestChainConfig
+}
+
+func (cfg AddRemoteChainToSolanaConfig) Validate(e deployment.Environment) error {
+ state, err := cs.LoadOnchainState(e)
+ if err != nil {
+ return fmt.Errorf("failed to load onchain state: %w", err)
+ }
+
+ supportedChains := state.SupportedChains()
+ for chainSel, updates := range cfg.UpdatesByChain {
+ chainState, ok := state.SolChains[chainSel]
+ if !ok {
+ return fmt.Errorf("chain %d not found in onchain state", chainSel)
+ }
+ chain := e.SolChains[chainSel]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return err
+ }
+ if err := commoncs.ValidateOwnershipSolana(e.GetContext(), cfg.MCMS != nil, e.SolChains[chainSel].DeployerKey.PublicKey(), chainState.Timelock, chainState.Router); err != nil {
+ return fmt.Errorf("failed to validate ownership: %w", err)
+ }
+ var routerConfigAccount solRouter.Config
+ // already validated that router config exists
+ _ = chain.GetAccountDataBorshInto(context.Background(), chainState.RouterConfigPDA, &routerConfigAccount)
+
+ for remote := range updates {
+ if _, ok := supportedChains[remote]; !ok {
+ return fmt.Errorf("remote chain %d is not supported", remote)
+ }
+ if remote == routerConfigAccount.SvmChainSelector {
+ return fmt.Errorf("cannot add remote chain %d with same chain selector as current chain %d", remote, chainSel)
+ }
+ }
+ }
+
+ return nil
+}
+
+// AddRemoteChainToSolana adds new remote chain configurations to Solana CCIP routers
+func AddRemoteChainToSolana(e deployment.Environment, cfg AddRemoteChainToSolanaConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ s, err := cs.LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ ab := deployment.NewMemoryAddressBook()
+ for chainSel, updates := range cfg.UpdatesByChain {
+ err := doAddRemoteChainToSolana(e, s, chainSel, updates, ab)
+ if err != nil {
+ return deployment.ChangesetOutput{AddressBook: ab}, err
+ }
+ }
+ return deployment.ChangesetOutput{AddressBook: ab}, nil
+}
+
+func doAddRemoteChainToSolana(
+ e deployment.Environment,
+ s cs.CCIPOnChainState,
+ chainSel uint64,
+ updates map[uint64]RemoteChainConfigSolana,
+ ab deployment.AddressBook) error {
+ chain := e.SolChains[chainSel]
+ ccipRouterID := s.SolChains[chainSel].Router
+
+ for remoteChainSel, update := range updates {
+ var onRampBytes [64]byte
+ // already verified, skipping errcheck
+ remoteChainFamily, _ := chainsel.GetSelectorFamily(remoteChainSel)
+ switch remoteChainFamily {
+ case chainsel.FamilySolana:
+ return fmt.Errorf("support for solana chain as remote chain is not implemented yet %d", remoteChainSel)
+ case chainsel.FamilyEVM:
+ onRampAddress := s.Chains[remoteChainSel].OnRamp.Address().String()
+ if onRampAddress == "" {
+ return fmt.Errorf("onramp address not found for chain %d", remoteChainSel)
+ }
+ addressBytes := []byte(onRampAddress)
+ copy(onRampBytes[:], addressBytes)
+ }
+
+ validSourceChainConfig := solRouter.SourceChainConfig{
+ OnRamp: [2][64]byte{onRampBytes, [64]byte{}},
+ IsEnabled: update.EnabledAsSource,
+ }
+ // addressing errcheck in the next PR
+ destChainStatePDA, _ := solState.FindDestChainStatePDA(remoteChainSel, ccipRouterID)
+ sourceChainStatePDA, _ := solState.FindSourceChainStatePDA(remoteChainSel, ccipRouterID)
+
+ instruction, err := solRouter.NewAddChainSelectorInstruction(
+ remoteChainSel,
+ validSourceChainConfig,
+ update.DestinationConfig,
+ sourceChainStatePDA,
+ destChainStatePDA,
+ s.SolChains[chainSel].RouterConfigPDA,
+ chain.DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+
+ if err != nil {
+ return fmt.Errorf("failed to generate instructions: %w", err)
+ }
+
+ err = chain.Confirm([]solana.Instruction{instruction})
+ if err != nil {
+ return fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ e.Logger.Infow("Confirmed instruction", "instruction", instruction)
+
+ tv := deployment.NewTypeAndVersion(cs.RemoteDest, deployment.Version1_0_0)
+ remoteChainSelStr := strconv.FormatUint(remoteChainSel, 10)
+ tv.AddLabel(remoteChainSelStr)
+ err = ab.Save(chainSel, destChainStatePDA.String(), tv)
+ if err != nil {
+ return fmt.Errorf("failed to save dest chain state to address book: %w", err)
+ }
+
+ tv = deployment.NewTypeAndVersion(cs.RemoteSource, deployment.Version1_0_0)
+ tv.AddLabel(remoteChainSelStr)
+ err = ab.Save(chainSel, sourceChainStatePDA.String(), tv)
+ if err != nil {
+ return fmt.Errorf("failed to save source chain state to address book: %w", err)
+ }
+ }
+
+ return nil
+}
+
+// SET OCR3 CONFIG
+func btoi(b bool) uint8 {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+// SetOCR3OffRamp will set the OCR3 offramp for the given chain.
+// to the active configuration on CCIPHome. This
+// is used to complete the candidate->active promotion cycle, it's
+// run after the candidate is confirmed to be working correctly.
+// Multichain is especially helpful for NOP rotations where we have
+// to touch all the chain to change signers.
+func SetOCR3ConfigSolana(e deployment.Environment, cfg cs.SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) {
+ state, err := cs.LoadOnchainState(e)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err)
+ }
+
+ if err := cfg.Validate(e, state); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ solChains := state.SolChains
+
+ // cfg.RemoteChainSels will be a bunch of solana chains
+ // can add this in validate
+ for _, remote := range cfg.RemoteChainSels {
+ donID, err := internal.DonIDForChain(
+ state.Chains[cfg.HomeChainSel].CapabilityRegistry,
+ state.Chains[cfg.HomeChainSel].CCIPHome,
+ remote)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to get don id for chain %d: %w", remote, err)
+ }
+ args, err := internal.BuildSetOCR3ConfigArgsSolana(donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to build set ocr3 config args: %w", err)
+ }
+ // TODO: check if ocr3 has already been set
+ // set, err := isOCR3ConfigSetSolana(e.Logger, e.Chains[remote], state.Chains[remote].OffRamp, args)
+ var instructions []solana.Instruction
+ routerConfigPDA := solChains[remote].RouterConfigPDA
+ routerStatePDA := solChains[remote].RouterStatePDA
+ for _, arg := range args {
+ instruction, err := solRouter.NewSetOcrConfigInstruction(
+ arg.OCRPluginType,
+ solRouter.Ocr3ConfigInfo{
+ ConfigDigest: arg.ConfigDigest,
+ F: arg.F,
+ IsSignatureVerificationEnabled: btoi(arg.IsSignatureVerificationEnabled),
+ },
+ arg.Signers,
+ arg.Transmitters,
+ routerConfigPDA,
+ routerStatePDA,
+ e.SolChains[remote].DeployerKey.PublicKey(),
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ instructions = append(instructions, instruction)
+ }
+ if cfg.MCMS == nil {
+ err := e.SolChains[remote].Confirm(instructions)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ }
+ }
+
+ return deployment.ChangesetOutput{}, nil
+
+ // TODO: timelock mcms support
+}
+
+// ADD TOKEN POOL
+type TokenPoolConfig struct {
+ ChainSelector uint64
+ PoolType string
+ Authority string
+ TokenPubKey string
+ TokenProgramName string
+}
+
+func (cfg TokenPoolConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ if chainState.TokenPool.IsZero() {
+ return fmt.Errorf("token pool not found in existing state, deploy the token pool first for chain %d", cfg.ChainSelector)
+ }
+ if _, err := GetPoolType(cfg.PoolType); err != nil {
+ return err
+ }
+ if _, err := GetTokenProgramID(cfg.TokenProgramName); err != nil {
+ return err
+ }
+
+ tokenPool := chainState.TokenPool
+ poolConfigPDA, err := solTokenUtil.TokenPoolConfigAddress(tokenPubKey, tokenPool)
+ if err != nil {
+ return fmt.Errorf("failed to get token pool config address (mint: %s, pool: %s): %w", tokenPubKey.String(), tokenPool.String(), err)
+ }
+ chain := e.SolChains[cfg.ChainSelector]
+ var poolConfigAccount token_pool.Config
+ if err := chain.GetAccountDataBorshInto(context.Background(), poolConfigPDA, &poolConfigAccount); err == nil {
+ return fmt.Errorf("token pool config already exists for (mint: %s, pool: %s)", tokenPubKey.String(), tokenPool.String())
+ }
+ return nil
+}
+
+func AddTokenPool(e deployment.Environment, cfg TokenPoolConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ authorityPubKey := solana.MustPublicKeyFromBase58(cfg.Authority)
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+
+ // verified
+ tokenprogramID, _ := GetTokenProgramID(cfg.TokenProgramName)
+ poolType, _ := GetPoolType(cfg.PoolType)
+ poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenPubKey, chainState.TokenPool)
+ poolSigner, _ := solTokenUtil.TokenPoolSignerAddress(tokenPubKey, chainState.TokenPool)
+
+ // addressing errcheck in the next PR
+ rampAuthorityPubKey, _, _ := solState.FindExternalExecutionConfigPDA(chainState.Router)
+
+ // ata for token pool
+ createI, tokenPoolATA, err := solTokenUtil.CreateAssociatedTokenAccount(
+ tokenprogramID,
+ tokenPubKey,
+ poolSigner,
+ chain.DeployerKey.PublicKey(),
+ )
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to create associated token account for tokenpool (mint: %s, pool: %s): %w", tokenPubKey.String(), chainState.TokenPool.String(), err)
+ }
+
+ token_pool.SetProgramID(chainState.TokenPool)
+ // initialize token pool for token
+ poolInitI, err := token_pool.NewInitializeInstruction(
+ poolType,
+ rampAuthorityPubKey,
+ poolConfigPDA,
+ tokenPubKey,
+ poolSigner,
+ authorityPubKey, // this is assumed to be chain.DeployerKey for now (owner of token pool)
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ // make pool mint_authority for token (required for burn/mint)
+ authI, err := solTokenUtil.SetTokenMintAuthority(
+ tokenprogramID,
+ poolSigner,
+ tokenPubKey,
+ chain.DeployerKey.PublicKey(),
+ )
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ instructions := []solana.Instruction{createI, poolInitI, authI}
+
+ // add signer here if authority is different from deployer key
+ if err := chain.Confirm(instructions); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ e.Logger.Infow("Created new token pool config", "token_pool_ata", tokenPoolATA.String(), "pool_config", poolConfigPDA.String(), "pool_signer", poolSigner.String())
+ e.Logger.Infow("Set mint authority", "poolSigner", poolSigner.String())
+
+ return deployment.ChangesetOutput{}, nil
+}
+
+// ADD TOKEN POOL FOR REMOTE CHAIN
+type RemoteChainTokenPoolConfig struct {
+ ChainSelector uint64
+ RemoteChainSelector uint64
+ TokenPubKey string
+ RemoteConfig token_pool.RemoteConfig
+ InboundRateLimit token_pool.RateLimitConfig
+ OutboundRateLimit token_pool.RateLimitConfig
+}
+
+func (cfg RemoteChainTokenPoolConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, solana.MustPublicKeyFromBase58(cfg.TokenPubKey)); err != nil {
+ return err
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ if chainState.TokenPool.IsZero() {
+ return fmt.Errorf("token pool not found in existing state, deploy token pool for chain %d", cfg.ChainSelector)
+ }
+
+ chain := e.SolChains[cfg.ChainSelector]
+ tokenPool := chainState.TokenPool
+
+ // check if pool config exists (cannot do remote setup without it)
+ poolConfigPDA, err := solTokenUtil.TokenPoolConfigAddress(tokenPubKey, tokenPool)
+ if err != nil {
+ return fmt.Errorf("failed to get token pool config address (mint: %s, pool: %s): %w", tokenPubKey.String(), tokenPool.String(), err)
+ }
+ var poolConfigAccount token_pool.Config
+ if err := chain.GetAccountDataBorshInto(context.Background(), poolConfigPDA, &poolConfigAccount); err != nil {
+ return fmt.Errorf("token pool config not found (mint: %s, pool: %s): %w", tokenPubKey.String(), chainState.TokenPool.String(), err)
+ }
+
+ // check if existing pool setup already has this remote chain configured
+ remoteChainConfigPDA, _, err := solTokenUtil.TokenPoolChainConfigPDA(cfg.RemoteChainSelector, tokenPubKey, tokenPool)
+ if err != nil {
+ return fmt.Errorf("failed to get token pool remote chain config pda (remoteSelector: %d, mint: %s, pool: %s): %w", cfg.RemoteChainSelector, tokenPubKey.String(), tokenPool.String(), err)
+ }
+ var remoteChainConfigAccount token_pool.ChainConfig
+ if err := chain.GetAccountDataBorshInto(context.Background(), remoteChainConfigPDA, &remoteChainConfigAccount); err == nil {
+ return fmt.Errorf("remote chain config already exists for (remoteSelector: %d, mint: %s, pool: %s)", cfg.RemoteChainSelector, tokenPubKey.String(), tokenPool.String())
+ }
+ return nil
+}
+
+func SetupTokenPoolForRemoteChain(e deployment.Environment, cfg RemoteChainTokenPoolConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ // verified
+ poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenPubKey, chainState.TokenPool)
+ remoteChainConfigPDA, _, _ := solTokenUtil.TokenPoolChainConfigPDA(cfg.RemoteChainSelector, tokenPubKey, chainState.TokenPool)
+
+ token_pool.SetProgramID(chainState.TokenPool)
+ ixConfigure, err := token_pool.NewInitChainRemoteConfigInstruction(
+ cfg.RemoteChainSelector,
+ tokenPubKey,
+ cfg.RemoteConfig,
+ poolConfigPDA,
+ remoteChainConfigPDA,
+ chain.DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ ixRates, err := token_pool.NewSetChainRateLimitInstruction(
+ cfg.RemoteChainSelector,
+ tokenPubKey,
+ cfg.InboundRateLimit,
+ cfg.OutboundRateLimit,
+ poolConfigPDA,
+ remoteChainConfigPDA,
+ chain.DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ instructions := []solana.Instruction{ixConfigure, ixRates}
+ err = chain.Confirm(instructions)
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ return deployment.ChangesetOutput{}, nil
+}
+
+// ADD BILLING TOKEN
+type BillingTokenConfig struct {
+ ChainSelector uint64
+ TokenPubKey string
+ TokenProgramName string
+ Config solRouter.BillingTokenConfig
+}
+
+func (cfg BillingTokenConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+ if _, err := GetTokenProgramID(cfg.TokenProgramName); err != nil {
+ return err
+ }
+
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return err
+ }
+ // check if already setup
+ billingConfigPDA, _, err := solState.FindFeeBillingTokenConfigPDA(tokenPubKey, chainState.Router)
+ if err != nil {
+ return fmt.Errorf("failed to find billing token config pda (mint: %s, router: %s): %w", tokenPubKey.String(), chainState.Router.String(), err)
+ }
+ var token0ConfigAccount solRouter.BillingTokenConfigWrapper
+ if err := chain.GetAccountDataBorshInto(context.Background(), billingConfigPDA, &token0ConfigAccount); err == nil {
+ return fmt.Errorf("billing token config already exists for (mint: %s, router: %s)", tokenPubKey.String(), chainState.Router.String())
+ }
+ return nil
+}
+
+func AddBillingToken(e deployment.Environment, cfg BillingTokenConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ chain, ok := e.SolChains[cfg.ChainSelector]
+ if !ok {
+ return deployment.ChangesetOutput{}, fmt.Errorf("chain selector %d not found in environment", cfg.ChainSelector)
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+
+ solRouter.SetProgramID(chainState.Router)
+
+ // verified
+ tokenprogramID, _ := GetTokenProgramID(cfg.TokenProgramName)
+ billingConfigPDA, _, _ := solState.FindFeeBillingTokenConfigPDA(tokenPubKey, chainState.Router)
+
+ // addressing errcheck in the next PR
+ billingSignerPDA, _, _ := solState.FindFeeBillingSignerPDA(chainState.Router)
+ token2022Receiver, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenprogramID, tokenPubKey, billingSignerPDA)
+
+ ixConfig, cerr := solRouter.NewAddBillingTokenConfigInstruction(
+ cfg.Config,
+ chainState.RouterConfigPDA,
+ billingConfigPDA,
+ tokenprogramID,
+ tokenPubKey,
+ token2022Receiver,
+ chain.DeployerKey.PublicKey(), // ccip admin
+ billingSignerPDA,
+ ata.ProgramID,
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if cerr != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", cerr)
+ }
+
+ instructions := []solana.Instruction{ixConfig}
+ if err := chain.Confirm(instructions); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ e.Logger.Infow("Billing token added", "chainSelector", cfg.ChainSelector, "tokenPubKey", tokenPubKey.String())
+ return deployment.ChangesetOutput{}, nil
+}
+
+// ADD BILLING TOKEN FOR REMOTE CHAIN
+type BillingTokenForRemoteChainConfig struct {
+ ChainSelector uint64
+ RemoteChainSelector uint64
+ Config solRouter.TokenBilling
+ TokenPubKey string
+}
+
+func (cfg BillingTokenForRemoteChainConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ chain := e.SolChains[cfg.ChainSelector]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return fmt.Errorf("router validation failed: %w", err)
+ }
+ // check if desired state already exists
+ remoteBillingPDA, _, err := solState.FindCcipTokenpoolBillingPDA(cfg.RemoteChainSelector, tokenPubKey, chainState.Router)
+ if err != nil {
+ return fmt.Errorf("failed to find remote billing token config pda for (remoteSelector: %d, mint: %s, router: %s): %w", cfg.RemoteChainSelector, tokenPubKey.String(), chainState.Router.String(), err)
+ }
+ var remoteBillingAccount solRouter.TokenBilling
+ if err := chain.GetAccountDataBorshInto(context.Background(), remoteBillingPDA, &remoteBillingAccount); err == nil {
+ return fmt.Errorf("billing token config already exists for (remoteSelector: %d, mint: %s, router: %s)", cfg.RemoteChainSelector, tokenPubKey.String(), chainState.Router.String())
+ }
+ return nil
+}
+
+func AddBillingTokenForRemoteChain(e deployment.Environment, cfg BillingTokenForRemoteChainConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ // verified
+ remoteBillingPDA, _, _ := solState.FindCcipTokenpoolBillingPDA(cfg.RemoteChainSelector, tokenPubKey, chainState.Router)
+
+ ix, err := solRouter.NewSetTokenBillingInstruction(
+ cfg.RemoteChainSelector,
+ tokenPubKey,
+ cfg.Config,
+ chainState.RouterConfigPDA,
+ remoteBillingPDA,
+ chain.DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ instructions := []solana.Instruction{ix}
+ if err := chain.Confirm(instructions); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ e.Logger.Infow("Token billing set for remote chain", "chainSelector ", cfg.ChainSelector, "remoteChainSelector ", cfg.RemoteChainSelector, "tokenPubKey", tokenPubKey.String())
+ return deployment.ChangesetOutput{}, nil
+}
+
+// TOKEN ADMIN REGISTRY
+type RegisterTokenAdminRegistryType int
+
+const (
+ ViaGetCcipAdminInstruction RegisterTokenAdminRegistryType = iota
+ ViaOwnerInstruction
+)
+
+type RegisterTokenAdminRegistryConfig struct {
+ ChainSelector uint64
+ TokenPubKey string
+ TokenAdminRegistryAdmin string
+ RegisterType RegisterTokenAdminRegistryType
+}
+
+func (cfg RegisterTokenAdminRegistryConfig) Validate(e deployment.Environment) error {
+ if cfg.RegisterType != ViaGetCcipAdminInstruction && cfg.RegisterType != ViaOwnerInstruction {
+ return fmt.Errorf("invalid register type, valid types are %d and %d", ViaGetCcipAdminInstruction, ViaOwnerInstruction)
+ }
+
+ if cfg.RegisterType == ViaOwnerInstruction && cfg.TokenAdminRegistryAdmin != "" {
+ return errors.New("token admin registry should be empty for via owner instruction")
+ }
+
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ chain := e.SolChains[cfg.ChainSelector]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return err
+ }
+ tokenAdminRegistryPDA, _, err := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+ if err != nil {
+ return fmt.Errorf("failed to find token admin registry pda (mint: %s, router: %s): %w", tokenPubKey.String(), chainState.Router.String(), err)
+ }
+ var tokenAdminRegistryAccount solRouter.TokenAdminRegistry
+ if err := chain.GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount); err == nil {
+ return fmt.Errorf("token admin registry already exists for (mint: %s, router: %s)", tokenPubKey.String(), chainState.Router.String())
+ }
+ return nil
+}
+
+func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdminRegistryConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+
+ // verified
+ tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+
+ var instruction *solRouter.Instruction
+ var err error
+ switch cfg.RegisterType {
+ // the ccip admin signs and makes tokenAdminRegistryAdmin the authority of the tokenAdminRegistry PDA
+ case ViaGetCcipAdminInstruction:
+ tokenAdminRegistryAdmin := solana.MustPublicKeyFromBase58(cfg.TokenAdminRegistryAdmin)
+ instruction, err = solRouter.NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction(
+ tokenPubKey,
+ tokenAdminRegistryAdmin, // admin of the tokenAdminRegistry PDA
+ chainState.RouterConfigPDA,
+ tokenAdminRegistryPDA, // this gets created
+ chain.DeployerKey.PublicKey(), // (ccip admin)
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ case ViaOwnerInstruction:
+ // the token mint authority signs and makes itself the authority of the tokenAdminRegistry PDA
+ instruction, err = solRouter.NewRegisterTokenAdminRegistryViaOwnerInstruction(
+ chainState.RouterConfigPDA,
+ tokenAdminRegistryPDA, // this gets created
+ tokenPubKey,
+ chain.DeployerKey.PublicKey(), // (token mint authority) becomes the authority of the tokenAdminRegistry PDA
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ }
+ // if we want to have a different authority, we will need to add the corresponding singer here
+ // for now we are assuming both token owner and ccip admin will always be deployer key
+ instructions := []solana.Instruction{instruction}
+ if err := chain.Confirm(instructions); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ return deployment.ChangesetOutput{}, nil
+}
+
+// TRANSFER AND ACCEPT TOKEN ADMIN REGISTRY
+type TransferAdminRoleTokenAdminRegistryConfig struct {
+ ChainSelector uint64
+ TokenPubKey string
+ NewRegistryAdminPublicKey string
+ CurrentRegistryAdminPrivateKey string
+}
+
+func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+
+ currentRegistryAdminPrivateKey := solana.MustPrivateKeyFromBase58(cfg.CurrentRegistryAdminPrivateKey)
+ newRegistryAdminPubKey := solana.MustPublicKeyFromBase58(cfg.NewRegistryAdminPublicKey)
+
+ if currentRegistryAdminPrivateKey.PublicKey().Equals(newRegistryAdminPubKey) {
+ return fmt.Errorf("new registry admin public key (%s) cannot be the same as current registry admin public key (%s) for token %s",
+ newRegistryAdminPubKey.String(),
+ currentRegistryAdminPrivateKey.PublicKey().String(),
+ tokenPubKey.String(),
+ )
+ }
+
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ chain := e.SolChains[cfg.ChainSelector]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return err
+ }
+ tokenAdminRegistryPDA, _, err := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+ if err != nil {
+ return fmt.Errorf("failed to find token admin registry pda (mint: %s, router: %s): %w", tokenPubKey.String(), chainState.Router.String(), err)
+ }
+ var tokenAdminRegistryAccount solRouter.TokenAdminRegistry
+ if err := chain.GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount); err != nil {
+ return fmt.Errorf("token admin registry not found for (mint: %s, router: %s), cannot transfer admin role", tokenPubKey.String(), chainState.Router.String())
+ }
+ // check if passed admin is the current admin
+ if !tokenAdminRegistryAccount.Administrator.Equals(currentRegistryAdminPrivateKey.PublicKey()) {
+ return fmt.Errorf("current registry admin private key (%s) does not match administrator (%s) for token %s",
+ currentRegistryAdminPrivateKey.PublicKey().String(),
+ tokenAdminRegistryAccount.Administrator.String(),
+ tokenPubKey.String(),
+ )
+ }
+ return nil
+}
+
+func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferAdminRoleTokenAdminRegistryConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+
+ // verified
+ tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+
+ currentRegistryAdminPrivateKey := solana.MustPrivateKeyFromBase58(cfg.CurrentRegistryAdminPrivateKey)
+ newRegistryAdminPubKey := solana.MustPublicKeyFromBase58(cfg.NewRegistryAdminPublicKey)
+
+ ix1, err := solRouter.NewTransferAdminRoleTokenAdminRegistryInstruction(
+ tokenPubKey,
+ newRegistryAdminPubKey,
+ chainState.RouterConfigPDA,
+ tokenAdminRegistryPDA,
+ currentRegistryAdminPrivateKey.PublicKey(), // as we are assuming this is the default authority for everything in the beginning
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+ instructions := []solana.Instruction{ix1}
+ // the existing authority will have to sign the transfer
+ if err := chain.Confirm(instructions, solCommonUtil.AddSigners(currentRegistryAdminPrivateKey)); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ return deployment.ChangesetOutput{}, nil
+}
+
+type AcceptAdminRoleTokenAdminRegistryConfig struct {
+ ChainSelector uint64
+ TokenPubKey string
+ NewRegistryAdminPrivateKey string
+}
+
+func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error {
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil {
+ return err
+ }
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ chain := e.SolChains[cfg.ChainSelector]
+ if err := validateRouterConfig(chain, chainState); err != nil {
+ return err
+ }
+ tokenAdminRegistryPDA, _, err := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+ if err != nil {
+ return fmt.Errorf("failed to find token admin registry pda (mint: %s, router: %s): %w", tokenPubKey.String(), chainState.Router.String(), err)
+ }
+ var tokenAdminRegistryAccount solRouter.TokenAdminRegistry
+ if err := chain.GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount); err != nil {
+ return fmt.Errorf("token admin registry not found for (mint: %s, router: %s), cannot accept admin role", tokenPubKey.String(), chainState.Router.String())
+ }
+ // check if accepting admin is the pending admin
+ newRegistryAdminPrivateKey := solana.MustPrivateKeyFromBase58(cfg.NewRegistryAdminPrivateKey)
+ newRegistryAdminPublicKey := newRegistryAdminPrivateKey.PublicKey()
+ if !tokenAdminRegistryAccount.PendingAdministrator.Equals(newRegistryAdminPublicKey) {
+ return fmt.Errorf("new admin public key (%s) does not match pending registry admin role (%s) for token %s",
+ newRegistryAdminPublicKey.String(),
+ tokenAdminRegistryAccount.PendingAdministrator.String(),
+ tokenPubKey.String(),
+ )
+ }
+ return nil
+}
+
+func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdminRoleTokenAdminRegistryConfig) (deployment.ChangesetOutput, error) {
+ if err := cfg.Validate(e); err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ chain := e.SolChains[cfg.ChainSelector]
+ state, _ := cs.LoadOnchainState(e)
+ chainState := state.SolChains[cfg.ChainSelector]
+ tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)
+ newRegistryAdminPrivateKey := solana.MustPrivateKeyFromBase58(cfg.NewRegistryAdminPrivateKey)
+
+ // verified
+ tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
+
+ ix1, err := solRouter.NewAcceptAdminRoleTokenAdminRegistryInstruction(
+ tokenPubKey,
+ chainState.RouterConfigPDA,
+ tokenAdminRegistryPDA,
+ newRegistryAdminPrivateKey.PublicKey(),
+ ).ValidateAndBuild()
+ if err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
+ }
+
+ instructions := []solana.Instruction{ix1}
+ // the new authority will have to sign the acceptance
+ if err := chain.Confirm(instructions, solCommonUtil.AddSigners(newRegistryAdminPrivateKey)); err != nil {
+ return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
+ }
+ return deployment.ChangesetOutput{}, nil
+}
+
+// TODO (all look up table related changesets):
+// Update look up tables with tokens and pools
+// Set Pool (https://smartcontract-it.atlassian.net/browse/INTAUTO-437)
+// NewAppendRemotePoolAddressesInstruction (https://smartcontract-it.atlassian.net/browse/INTAUTO-436)
diff --git a/deployment/ccip/changeset/solana/cs_chain_contracts_test.go b/deployment/ccip/changeset/solana/cs_chain_contracts_test.go
new file mode 100644
index 00000000000..a8e122d48a7
--- /dev/null
+++ b/deployment/ccip/changeset/solana/cs_chain_contracts_test.go
@@ -0,0 +1,351 @@
+package solana_test
+
+import (
+ "context"
+ "math/big"
+ "testing"
+
+ "github.com/gagliardetto/solana-go"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink/deployment"
+
+ solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"
+ "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/token_pool"
+ solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"
+ solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens"
+ "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+
+ commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+)
+
+func TestAddRemoteChain(t *testing.T) {
+ t.Parallel()
+ ctx := testcontext.Get(t)
+ // Default env just has 2 chains with all contracts
+ // deployed but no lanes.
+ tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1))
+
+ evmChain := tenv.Env.AllChainSelectors()[0]
+ solChain := tenv.Env.AllChainSelectorsSolana()[0]
+
+ state, err := changeset.LoadOnchainState(tenv.Env)
+ require.NoError(t, err)
+
+ tenv.Env, err = commonchangeset.ApplyChangesets(t, tenv.Env, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset),
+ Config: changeset.UpdateOnRampDestsConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{
+ evmChain: {
+ solChain: {
+ IsEnabled: true,
+ TestRouter: false,
+ AllowListEnabled: false,
+ },
+ },
+ },
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.AddRemoteChainToSolana),
+ Config: changeset_solana.AddRemoteChainToSolanaConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset_solana.RemoteChainConfigSolana{
+ solChain: {
+ evmChain: {
+ EnabledAsSource: true,
+ DestinationConfig: solRouter.DestChainConfig{
+ IsEnabled: true,
+ DefaultTxGasLimit: 200000,
+ MaxPerMsgGasLimit: 3000000,
+ MaxDataBytes: 30000,
+ MaxNumberOfTokensPerMsg: 5,
+ DefaultTokenDestGasOverhead: 5000,
+ // bytes4(keccak256("CCIP ChainFamilySelector EVM"))
+ // TODO: do a similar test for other chain families
+ // https://smartcontract-it.atlassian.net/browse/INTAUTO-438
+ ChainFamilySelector: [4]uint8{40, 18, 213, 44},
+ },
+ },
+ },
+ },
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ state, err = changeset.LoadOnchainStateSolana(tenv.Env)
+ require.NoError(t, err)
+ var sourceChainStateAccount solRouter.SourceChain
+ evmSourceChainStatePDA := state.SolChains[solChain].SourceChainStatePDAs[evmChain]
+ err = tenv.Env.SolChains[solChain].GetAccountDataBorshInto(ctx, evmSourceChainStatePDA, &sourceChainStateAccount)
+ require.NoError(t, err)
+ require.Equal(t, uint64(1), sourceChainStateAccount.State.MinSeqNr)
+ require.True(t, sourceChainStateAccount.Config.IsEnabled)
+
+ var destChainStateAccount solRouter.DestChain
+ evmDestChainStatePDA := state.SolChains[solChain].DestChainStatePDAs[evmChain]
+ err = tenv.Env.SolChains[solChain].GetAccountDataBorshInto(ctx, evmDestChainStatePDA, &destChainStateAccount)
+ require.NoError(t, err)
+}
+
+func TestDeployCCIPContracts(t *testing.T) {
+ t.Parallel()
+ testhelpers.DeployCCIPContractsTest(t, 1)
+}
+
+func TestAddTokenPool(t *testing.T) {
+ t.Parallel()
+
+ tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1))
+
+ evmChain := tenv.Env.AllChainSelectors()[0]
+ solChain := tenv.Env.AllChainSelectorsSolana()[0]
+
+ e, err := commonchangeset.ApplyChangesets(t, tenv.Env, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.DeploySolanaToken),
+ Config: changeset_solana.DeploySolanaTokenConfig{
+ ChainSelector: solChain,
+ TokenProgramName: deployment.SPL2022Tokens,
+ TokenDecimals: 9,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ state, err := ccipChangeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err)
+ tokenAddress := state.SolChains[solChain].SPL2022Tokens[0]
+
+ // TODO: can test this with solana.SolMint as well (WSOL)
+ // https://smartcontract-it.atlassian.net/browse/INTAUTO-440
+ e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.AddTokenPool),
+ Config: changeset_solana.TokenPoolConfig{
+ ChainSelector: solChain,
+ TokenPubKey: tokenAddress.String(),
+ TokenProgramName: deployment.SPL2022Tokens,
+ PoolType: "LockAndRelease",
+ // this works for testing, but if we really want some other authority we need to pass in a private key for signing purposes
+ Authority: e.SolChains[solChain].DeployerKey.PublicKey().String(),
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.SetupTokenPoolForRemoteChain),
+ Config: changeset_solana.RemoteChainTokenPoolConfig{
+ ChainSelector: solChain,
+ RemoteChainSelector: evmChain,
+ TokenPubKey: tokenAddress.String(),
+ RemoteConfig: token_pool.RemoteConfig{
+ PoolAddresses: []token_pool.RemoteAddress{{Address: []byte{1, 2, 3}}},
+ TokenAddress: token_pool.RemoteAddress{Address: []byte{4, 5, 6}},
+ Decimals: 9,
+ },
+ InboundRateLimit: token_pool.RateLimitConfig{
+ Enabled: true,
+ Capacity: uint64(1000),
+ Rate: 1,
+ },
+ OutboundRateLimit: token_pool.RateLimitConfig{
+ Enabled: false,
+ Capacity: 0,
+ Rate: 0,
+ },
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ // test AddTokenPool results
+ poolConfigPDA, err := solTokenUtil.TokenPoolConfigAddress(tokenAddress, state.SolChains[solChain].TokenPool)
+ require.NoError(t, err)
+ var configAccount token_pool.Config
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), poolConfigPDA, &configAccount)
+ t.Logf("configAccount: %+v", configAccount)
+ require.NoError(t, err)
+ require.Equal(t, token_pool.LockAndRelease_PoolType, configAccount.PoolType)
+ require.Equal(t, tokenAddress, configAccount.Mint)
+ // try minting after this and see if the pool or the deployer key is the authority
+
+ // test SetupTokenPoolForRemoteChain results
+ remoteChainConfigPDA, _, _ := solTokenUtil.TokenPoolChainConfigPDA(evmChain, tokenAddress, state.SolChains[solChain].TokenPool)
+ var remoteChainConfigAccount token_pool.ChainConfig
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), remoteChainConfigPDA, &remoteChainConfigAccount)
+ require.NoError(t, err)
+ require.Equal(t, uint8(9), remoteChainConfigAccount.Remote.Decimals)
+}
+
+func TestBilling(t *testing.T) {
+ t.Parallel()
+
+ tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1))
+
+ evmChain := tenv.Env.AllChainSelectors()[0]
+ solChain := tenv.Env.AllChainSelectorsSolana()[0]
+
+ e, err := commonchangeset.ApplyChangesets(t, tenv.Env, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.DeploySolanaToken),
+ Config: changeset_solana.DeploySolanaTokenConfig{
+ ChainSelector: solChain,
+ TokenProgramName: deployment.SPL2022Tokens,
+ TokenDecimals: 9,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ state, err := ccipChangeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err)
+ tokenAddress := state.SolChains[solChain].SPL2022Tokens[0]
+ validTimestamp := int64(100)
+ value := [28]uint8{}
+ bigNum, ok := new(big.Int).SetString("19816680000000000000", 10)
+ require.True(t, ok)
+ bigNum.FillBytes(value[:])
+ e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.AddBillingToken),
+ Config: changeset_solana.BillingTokenConfig{
+ ChainSelector: solChain,
+ TokenPubKey: tokenAddress.String(),
+ TokenProgramName: deployment.SPL2022Tokens,
+ Config: solRouter.BillingTokenConfig{
+ Enabled: true,
+ Mint: tokenAddress,
+ UsdPerToken: solRouter.TimestampedPackedU224{
+ Timestamp: validTimestamp,
+ Value: value,
+ },
+ PremiumMultiplierWeiPerEth: 100,
+ },
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.AddBillingTokenForRemoteChain),
+ Config: changeset_solana.BillingTokenForRemoteChainConfig{
+ ChainSelector: solChain,
+ RemoteChainSelector: evmChain,
+ TokenPubKey: tokenAddress.String(),
+ Config: solRouter.TokenBilling{
+ MinFeeUsdcents: 800,
+ MaxFeeUsdcents: 1600,
+ DeciBps: 0,
+ DestGasOverhead: 100,
+ DestBytesOverhead: 100,
+ IsEnabled: true,
+ },
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ billingConfigPDA, _, _ := solState.FindFeeBillingTokenConfigPDA(tokenAddress, state.SolChains[solChain].Router)
+ var token0ConfigAccount solRouter.BillingTokenConfigWrapper
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), billingConfigPDA, &token0ConfigAccount)
+ require.NoError(t, err)
+ require.True(t, token0ConfigAccount.Config.Enabled)
+ require.Equal(t, tokenAddress, token0ConfigAccount.Config.Mint)
+
+ remoteBillingPDA, _, _ := solState.FindCcipTokenpoolBillingPDA(evmChain, tokenAddress, state.SolChains[solChain].Router)
+ var remoteBillingAccount solRouter.PerChainPerTokenConfig
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), remoteBillingPDA, &remoteBillingAccount)
+ require.NoError(t, err)
+ require.Equal(t, tokenAddress, remoteBillingAccount.Mint)
+ require.Equal(t, uint32(800), remoteBillingAccount.Billing.MinFeeUsdcents)
+}
+
+func TestTokenAdminRegistry(t *testing.T) {
+ t.Parallel()
+
+ tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1))
+
+ solChain := tenv.Env.AllChainSelectorsSolana()[0]
+
+ e, err := commonchangeset.ApplyChangesets(t, tenv.Env, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.DeploySolanaToken),
+ Config: changeset_solana.DeploySolanaTokenConfig{
+ ChainSelector: solChain,
+ TokenProgramName: deployment.SPL2022Tokens,
+ TokenDecimals: 9,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ state, err := ccipChangeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err)
+ tokenAddress := state.SolChains[solChain].SPL2022Tokens[0]
+ tokenAdminRegistryAdminPrivKey, _ := solana.NewRandomPrivateKey()
+
+ // We have to do run the ViaOwnerInstruction testcase for linkToken as we already registered a PDA for tokenAddress in the previous testcase
+ linkTokenAddress := state.SolChains[solChain].LinkToken
+
+ e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ { // register token admin registry for tokenAddress via getCcipAdminInstruction
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.RegisterTokenAdminRegistry),
+ Config: changeset_solana.RegisterTokenAdminRegistryConfig{
+ ChainSelector: solChain,
+ TokenPubKey: tokenAddress.String(),
+ TokenAdminRegistryAdmin: tokenAdminRegistryAdminPrivKey.PublicKey().String(),
+ RegisterType: changeset_solana.ViaGetCcipAdminInstruction,
+ },
+ },
+ { // register token admin registry for linkToken via owner instruction
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.RegisterTokenAdminRegistry),
+ Config: changeset_solana.RegisterTokenAdminRegistryConfig{
+ ChainSelector: solChain,
+ TokenPubKey: linkTokenAddress.String(),
+ RegisterType: changeset_solana.ViaOwnerInstruction,
+ },
+ },
+ { // transfer admin role for tokenAddress
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.TransferAdminRoleTokenAdminRegistry),
+ Config: changeset_solana.TransferAdminRoleTokenAdminRegistryConfig{
+ ChainSelector: solChain,
+ TokenPubKey: tokenAddress.String(),
+ CurrentRegistryAdminPrivateKey: tokenAdminRegistryAdminPrivKey.String(),
+ NewRegistryAdminPublicKey: e.SolChains[solChain].DeployerKey.PublicKey().String(),
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenAddress, state.SolChains[solChain].Router)
+ var tokenAdminRegistryAccount solRouter.TokenAdminRegistry
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
+ require.NoError(t, err)
+ require.Equal(t, tokenAdminRegistryAdminPrivKey.PublicKey(), tokenAdminRegistryAccount.Administrator)
+ // pending administrator should be the deployer key
+ require.Equal(t, e.SolChains[solChain].DeployerKey.PublicKey(), tokenAdminRegistryAccount.PendingAdministrator)
+
+ linkTokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(linkTokenAddress, state.SolChains[solChain].Router)
+ var linkTokenAdminRegistryAccount solRouter.TokenAdminRegistry
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), linkTokenAdminRegistryPDA, &linkTokenAdminRegistryAccount)
+ require.NoError(t, err)
+ // as DeployLinkToken (DeploySolanaToken) makes the deployer key the authority of the token, it should be the administrator of the tokenAdminRegistry via owner instruction
+ require.Equal(t, e.SolChains[solChain].DeployerKey.PublicKey(), linkTokenAdminRegistryAccount.Administrator)
+
+ e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ { // accept admin role for tokenAddress
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.AcceptAdminRoleTokenAdminRegistry),
+ Config: changeset_solana.AcceptAdminRoleTokenAdminRegistryConfig{
+ ChainSelector: solChain,
+ TokenPubKey: tokenAddress.String(),
+ NewRegistryAdminPrivateKey: e.SolChains[solChain].DeployerKey.String(),
+ },
+ },
+ })
+ require.NoError(t, err)
+ err = e.SolChains[solChain].GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
+ require.NoError(t, err)
+ // confirm that the administrator is the deployer key
+ require.Equal(t, e.SolChains[solChain].DeployerKey.PublicKey(), tokenAdminRegistryAccount.Administrator)
+}
diff --git a/deployment/ccip/changeset/solana/cs_deploy_chain_test.go b/deployment/ccip/changeset/solana/cs_deploy_chain_test.go
new file mode 100644
index 00000000000..01416f0dd23
--- /dev/null
+++ b/deployment/ccip/changeset/solana/cs_deploy_chain_test.go
@@ -0,0 +1,121 @@
+package solana_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap/zapcore"
+
+ "github.com/smartcontractkit/chainlink/deployment"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+ "github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
+ "github.com/smartcontractkit/chainlink/deployment/environment/memory"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+
+ commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+ commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
+)
+
+func TestDeployChainContractsChangeset(t *testing.T) {
+ t.Parallel()
+ lggr := logger.TestLogger(t)
+ e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
+ Bootstraps: 1,
+ Chains: 2,
+ SolChains: 1,
+ Nodes: 4,
+ })
+ evmSelectors := e.AllChainSelectors()
+ homeChainSel := evmSelectors[0]
+ solChainSelectors := e.AllChainSelectorsSolana()
+ selectors := make([]uint64, 0, len(evmSelectors)+len(solChainSelectors))
+ selectors = append(selectors, evmSelectors...)
+ selectors = append(selectors, solChainSelectors...)
+ nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)
+ require.NoError(t, err)
+ cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig)
+ contractParams := make(map[uint64]changeset.ChainContractParams)
+ for _, chain := range e.AllChainSelectors() {
+ cfg[chain] = proposalutils.SingleGroupTimelockConfig(t)
+ contractParams[chain] = changeset.ChainContractParams{
+ FeeQuoterParams: changeset.DefaultFeeQuoterParams(),
+ OffRampParams: changeset.DefaultOffRampParams(),
+ }
+ }
+ for _, chain := range solChainSelectors {
+ contractParams[chain] = changeset.ChainContractParams{
+ FeeQuoterParams: changeset.DefaultFeeQuoterParams(),
+ OffRampParams: changeset.DefaultOffRampParams(),
+ }
+ }
+ prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0)
+ for _, chain := range e.AllChainSelectors() {
+ prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{
+ ChainSelector: chain,
+ })
+ }
+
+ testhelpers.SavePreloadedSolAddresses(t, e, solChainSelectors[0])
+ e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset),
+ Config: changeset.DeployHomeChainConfig{
+ HomeChainSel: homeChainSel,
+ RMNStaticConfig: testhelpers.NewTestRMNStaticConfig(),
+ RMNDynamicConfig: testhelpers.NewTestRMNDynamicConfig(),
+ NodeOperators: testhelpers.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From),
+ NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{
+ testhelpers.TestNodeOperator: nodes.NonBootstraps().PeerIDs(),
+ },
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
+ Config: selectors,
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
+ Config: cfg,
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset),
+ Config: changeset.DeployPrerequisiteConfig{
+ Configs: prereqCfg,
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContractsChangeset),
+ Config: changeset.DeployChainContractsConfig{
+ HomeChainSelector: homeChainSel,
+ ContractParamsPerChain: contractParams,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ // load onchain state
+ state, err := changeset.LoadOnchainState(e)
+ require.NoError(t, err)
+
+ // verify all contracts populated
+ require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry)
+ require.NotNil(t, state.Chains[homeChainSel].CCIPHome)
+ require.NotNil(t, state.Chains[homeChainSel].RMNHome)
+ for _, sel := range evmSelectors {
+ require.NotNil(t, state.Chains[sel].LinkToken)
+ require.NotNil(t, state.Chains[sel].Weth9)
+ require.NotNil(t, state.Chains[sel].TokenAdminRegistry)
+ require.NotNil(t, state.Chains[sel].RegistryModule)
+ require.NotNil(t, state.Chains[sel].Router)
+ require.NotNil(t, state.Chains[sel].RMNRemote)
+ require.NotNil(t, state.Chains[sel].TestRouter)
+ require.NotNil(t, state.Chains[sel].NonceManager)
+ require.NotNil(t, state.Chains[sel].FeeQuoter)
+ require.NotNil(t, state.Chains[sel].OffRamp)
+ require.NotNil(t, state.Chains[sel].OnRamp)
+ }
+
+ // solana verification
+ testhelpers.ValidateSolanaState(t, e, solChainSelectors)
+}
diff --git a/deployment/ccip/changeset/solana/cs_solana_token.go b/deployment/ccip/changeset/solana/cs_solana_token.go
new file mode 100644
index 00000000000..e34584a7247
--- /dev/null
+++ b/deployment/ccip/changeset/solana/cs_solana_token.go
@@ -0,0 +1,157 @@
+package solana
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/gagliardetto/solana-go"
+
+ "github.com/smartcontractkit/chainlink/deployment"
+
+ solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
+ solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens"
+)
+
+var _ deployment.ChangeSet[DeploySolanaTokenConfig] = DeploySolanaToken
+var _ deployment.ChangeSet[MintSolanaTokenConfig] = MintSolanaToken
+var _ deployment.ChangeSet[CreateSolanaTokenATAConfig] = CreateSolanaTokenATA
+
+type DeploySolanaTokenConfig struct {
+ ChainSelector uint64
+ TokenProgramName string
+ TokenDecimals uint8
+}
+
+func NewTokenInstruction(chain deployment.SolChain, cfg DeploySolanaTokenConfig) ([]solana.Instruction, solana.PrivateKey, error) {
+ tokenprogramID, err := GetTokenProgramID(cfg.TokenProgramName)
+ if err != nil {
+ return nil, nil, err
+ }
+ tokenAdminPubKey := chain.DeployerKey.PublicKey()
+ mint, _ := solana.NewRandomPrivateKey()
+ mintPublicKey := mint.PublicKey() // this is the token address
+ instructions, err := solTokenUtil.CreateToken(
+ context.Background(),
+ tokenprogramID,
+ mintPublicKey,
+ tokenAdminPubKey,
+ cfg.TokenDecimals,
+ chain.Client,
+ deployment.SolDefaultCommitment,
+ )
+ if err != nil {
+ return nil, nil, err
+ }
+ return instructions, mint, nil
+}
+
+func DeploySolanaToken(e deployment.Environment, cfg DeploySolanaTokenConfig) (deployment.ChangesetOutput, error) {
+ chain, ok := e.SolChains[cfg.ChainSelector]
+ if !ok {
+ return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found in environment", cfg.ChainSelector)
+ }
+ instructions, mint, err := NewTokenInstruction(chain, cfg)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ err = chain.Confirm(instructions, solCommomUtil.AddSigners(mint))
+ if err != nil {
+ e.Logger.Errorw("Failed to confirm instructions for link token deployment", "chain", chain.String(), "err", err)
+ return deployment.ChangesetOutput{}, err
+ }
+
+ newAddresses := deployment.NewMemoryAddressBook()
+ tv := deployment.NewTypeAndVersion(deployment.ContractType(cfg.TokenProgramName), deployment.Version1_0_0)
+ err = newAddresses.Save(cfg.ChainSelector, mint.PublicKey().String(), tv)
+ if err != nil {
+ e.Logger.Errorw("Failed to save link token", "chain", chain.String(), "err", err)
+ return deployment.ChangesetOutput{}, err
+ }
+
+ e.Logger.Infow("Deployed contract", "Contract", tv.String(), "addr", mint.PublicKey().String(), "chain", chain.String())
+
+ return deployment.ChangesetOutput{
+ AddressBook: newAddresses,
+ }, nil
+}
+
+// TODO: there is no validation done around if the token is already deployed
+// https://smartcontract-it.atlassian.net/browse/INTAUTO-439
+type MintSolanaTokenConfig struct {
+ ChainSelector uint64
+ TokenProgram string
+ TokenPubkey solana.PublicKey
+ AmountToAddress map[string]uint64 // address -> amount
+}
+
+func MintSolanaToken(e deployment.Environment, cfg MintSolanaTokenConfig) (deployment.ChangesetOutput, error) {
+ // get chain
+ chain := e.SolChains[cfg.ChainSelector]
+ // get addresses
+ tokenAddress := cfg.TokenPubkey
+ // get token program id
+ tokenprogramID, err := GetTokenProgramID(cfg.TokenProgram)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ // get mint instructions
+ instructions := []solana.Instruction{}
+ for toAddress, amount := range cfg.AmountToAddress {
+ toAddressBase58 := solana.MustPublicKeyFromBase58(toAddress)
+ // get associated token account for toAddress
+ ata, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenprogramID, tokenAddress, toAddressBase58)
+ mintToI, err := solTokenUtil.MintTo(amount, tokenprogramID, tokenAddress, ata, chain.DeployerKey.PublicKey())
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ instructions = append(instructions, mintToI)
+ }
+ // confirm instructions
+ err = chain.Confirm(instructions)
+ if err != nil {
+ e.Logger.Errorw("Failed to confirm instructions for token minting", "chain", chain.String(), "err", err)
+ return deployment.ChangesetOutput{}, err
+ }
+ return deployment.ChangesetOutput{}, nil
+}
+
+type CreateSolanaTokenATAConfig struct {
+ ChainSelector uint64
+ TokenPubkey solana.PublicKey
+ TokenProgram string
+ ATAList []string // addresses to create ATAs for
+}
+
+func CreateSolanaTokenATA(e deployment.Environment, cfg CreateSolanaTokenATAConfig) (deployment.ChangesetOutput, error) {
+ chain := e.SolChains[cfg.ChainSelector]
+
+ tokenprogramID, err := GetTokenProgramID(cfg.TokenProgram)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+
+ // create instructions for each ATA
+ instructions := []solana.Instruction{}
+ for _, ata := range cfg.ATAList {
+ createATAIx, _, err := solTokenUtil.CreateAssociatedTokenAccount(
+ tokenprogramID,
+ cfg.TokenPubkey,
+ solana.MustPublicKeyFromBase58(ata),
+ chain.DeployerKey.PublicKey(),
+ )
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ instructions = append(instructions, createATAIx)
+ }
+
+ // confirm instructions
+ err = chain.Confirm(instructions)
+ if err != nil {
+ e.Logger.Errorw("Failed to confirm instructions for ATA creation", "chain", chain.String(), "err", err)
+ return deployment.ChangesetOutput{}, err
+ }
+
+ return deployment.ChangesetOutput{}, nil
+}
diff --git a/deployment/ccip/changeset/solana/cs_solana_token_test.go b/deployment/ccip/changeset/solana/cs_solana_token_test.go
new file mode 100644
index 00000000000..67573b20c71
--- /dev/null
+++ b/deployment/ccip/changeset/solana/cs_solana_token_test.go
@@ -0,0 +1,81 @@
+package solana_test
+
+import (
+ "context"
+ "testing"
+
+ "github.com/gagliardetto/solana-go"
+ solRpc "github.com/gagliardetto/solana-go/rpc"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap/zapcore"
+
+ solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens"
+ "github.com/smartcontractkit/chainlink/deployment"
+ ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+ "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+ commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+ "github.com/smartcontractkit/chainlink/deployment/environment/memory"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+func TestSolanaTokenOps(t *testing.T) {
+ t.Parallel()
+ lggr := logger.TestLogger(t)
+ e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
+ SolChains: 1,
+ })
+ solChain1 := e.AllChainSelectorsSolana()[0]
+ e, err := commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.DeploySolanaToken),
+ Config: changeset_solana.DeploySolanaTokenConfig{
+ ChainSelector: solChain1,
+ TokenProgramName: deployment.SPL2022Tokens,
+ TokenDecimals: 9,
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ state, err := ccipChangeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err)
+ tokenAddress := state.SolChains[solChain1].SPL2022Tokens[0]
+ testUser, _ := solana.NewRandomPrivateKey()
+ testUserPubKey := testUser.PublicKey()
+
+ e, err = changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{
+ {
+ Changeset: changeset.WrapChangeSet(changeset_solana.CreateSolanaTokenATA),
+ Config: changeset_solana.CreateSolanaTokenATAConfig{
+ ChainSelector: solChain1,
+ TokenPubkey: tokenAddress,
+ TokenProgram: deployment.SPL2022Tokens,
+ ATAList: []string{testUserPubKey.String()},
+ },
+ },
+ {
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.MintSolanaToken),
+ Config: changeset_solana.MintSolanaTokenConfig{
+ ChainSelector: solChain1,
+ TokenPubkey: tokenAddress,
+ TokenProgram: deployment.SPL2022Tokens,
+ AmountToAddress: map[string]uint64{
+ testUserPubKey.String(): uint64(1000),
+ },
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ ata, _, _ := solTokenUtil.FindAssociatedTokenAddress(solana.Token2022ProgramID, tokenAddress, testUserPubKey)
+ outDec, outVal, err := solTokenUtil.TokenBalance(context.Background(), e.SolChains[solChain1].Client, ata, solRpc.CommitmentConfirmed)
+ require.NoError(t, err)
+ require.Equal(t, int(1000), outVal)
+ require.Equal(t, 9, int(outDec))
+}
+
+func TestDeployLinkToken(t *testing.T) {
+ testhelpers.DeployLinkTokenTest(t, 1)
+}
diff --git a/deployment/ccip/changeset/solana/save_existing_test.go b/deployment/ccip/changeset/solana/save_existing_test.go
new file mode 100644
index 00000000000..bf2bff21a61
--- /dev/null
+++ b/deployment/ccip/changeset/solana/save_existing_test.go
@@ -0,0 +1,89 @@
+package solana_test
+
+import (
+ "testing"
+
+ "github.com/gagliardetto/solana-go"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/zap/zapcore"
+
+ chainsel "github.com/smartcontractkit/chain-selectors"
+
+ "github.com/smartcontractkit/chainlink/deployment"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
+ commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
+ "github.com/smartcontractkit/chainlink/deployment/environment/memory"
+ "github.com/smartcontractkit/chainlink/v2/core/logger"
+)
+
+func TestSaveExistingCCIP(t *testing.T) {
+ t.Parallel()
+ lggr := logger.TestLogger(t)
+ e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
+ Bootstraps: 1,
+ Chains: 2,
+ SolChains: 1,
+ Nodes: 4,
+ })
+ solChain := e.AllChainSelectorsSolana()[0]
+ solAddr1 := solana.NewWallet().PublicKey().String()
+ solAddr2 := solana.NewWallet().PublicKey().String()
+ cfg := commonchangeset.ExistingContractsConfig{
+ ExistingContracts: []commonchangeset.Contract{
+ {
+ Address: solAddr1,
+ TypeAndVersion: deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_0_0),
+ ChainSelector: solChain,
+ },
+ {
+ Address: solAddr2,
+ TypeAndVersion: deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0),
+ ChainSelector: solChain,
+ },
+ },
+ }
+
+ output, err := commonchangeset.SaveExistingContractsChangeset(e, cfg)
+ require.NoError(t, err)
+ err = e.ExistingAddresses.Merge(output.AddressBook)
+ require.NoError(t, err)
+ state, err := changeset.LoadOnchainState(e)
+ require.NoError(t, err)
+ require.Equal(t, state.SolChains[solChain].Router.String(), solAddr1)
+ require.Equal(t, state.SolChains[solChain].LinkToken.String(), solAddr2)
+}
+
+func TestSaveExisting(t *testing.T) {
+ t.Parallel()
+ dummyEnv := deployment.Environment{
+ Name: "dummy",
+ Logger: logger.TestLogger(t),
+ ExistingAddresses: deployment.NewMemoryAddressBook(),
+ SolChains: map[uint64]deployment.SolChain{
+ chainsel.SOLANA_DEVNET.Selector: {},
+ },
+ }
+ ExistingContracts := commonchangeset.ExistingContractsConfig{
+ ExistingContracts: []commonchangeset.Contract{
+ {
+ Address: solana.NewWallet().PublicKey().String(),
+ TypeAndVersion: deployment.TypeAndVersion{
+ Type: "dummy3",
+ Version: deployment.Version1_1_0,
+ },
+ ChainSelector: chainsel.SOLANA_DEVNET.Selector,
+ },
+ },
+ }
+
+ output, err := commonchangeset.SaveExistingContractsChangeset(dummyEnv, ExistingContracts)
+ require.NoError(t, err)
+ require.NoError(t, dummyEnv.ExistingAddresses.Merge(output.AddressBook))
+ addresses, err := dummyEnv.ExistingAddresses.Addresses()
+ require.NoError(t, err)
+ require.Len(t, addresses, 1)
+ addressForSolana, exists := addresses[chainsel.SOLANA_DEVNET.Selector]
+ require.True(t, exists)
+ require.Len(t, addressForSolana, 1)
+}
diff --git a/deployment/ccip/changeset/solana_state.go b/deployment/ccip/changeset/solana_state.go
index 68a326f471d..1a4e8161a88 100644
--- a/deployment/ccip/changeset/solana_state.go
+++ b/deployment/ccip/changeset/solana_state.go
@@ -1,25 +1,45 @@
package changeset
import (
- "encoding/binary"
"errors"
"fmt"
+ "strconv"
"github.com/gagliardetto/solana-go"
+ solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"
+
"github.com/smartcontractkit/chainlink/deployment"
+ commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
)
var (
- LinkToken deployment.ContractType = "LinkToken"
- SolCcipRouter deployment.ContractType = "SolCcipRouter"
+ AddressLookupTable deployment.ContractType = "AddressLookupTable"
+ TokenPool deployment.ContractType = "TokenPool"
+ Receiver deployment.ContractType = "Receiver"
+ SPL2022Tokens deployment.ContractType = "SPL2022Tokens"
+ WSOL deployment.ContractType = "WSOL"
+ // for PDAs from AddRemoteChainToSolana
+ RemoteSource deployment.ContractType = "RemoteSource"
+ RemoteDest deployment.ContractType = "RemoteDest"
)
// SolChainState holds a Go binding for all the currently deployed CCIP programs
// on a chain. If a binding is nil, it means here is no such contract on the chain.
type SolCCIPChainState struct {
- LinkToken solana.PublicKey
- SolCcipRouter solana.PublicKey
+ LinkToken solana.PublicKey
+ Router solana.PublicKey
+ Timelock solana.PublicKey
+ AddressLookupTable solana.PublicKey // for chain writer
+ Receiver solana.PublicKey // for tests only
+ SPL2022Tokens []solana.PublicKey
+ TokenPool solana.PublicKey
+ WSOL solana.PublicKey
+ // PDAs to avoid redundant lookups
+ RouterStatePDA solana.PublicKey
+ RouterConfigPDA solana.PublicKey
+ SourceChainStatePDAs map[uint64]solana.PublicKey
+ DestChainStatePDAs map[uint64]solana.PublicKey
}
func LoadOnchainStateSolana(e deployment.Environment) (CCIPOnChainState, error) {
@@ -46,102 +66,66 @@ func LoadOnchainStateSolana(e deployment.Environment) (CCIPOnChainState, error)
// LoadChainStateSolana Loads all state for a SolChain into state
func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]deployment.TypeAndVersion) (SolCCIPChainState, error) {
- var state SolCCIPChainState
+ state := SolCCIPChainState{
+ SourceChainStatePDAs: make(map[uint64]solana.PublicKey),
+ DestChainStatePDAs: make(map[uint64]solana.PublicKey),
+ }
+ var spl2022Tokens []solana.PublicKey
for address, tvStr := range addresses {
- switch tvStr.String() {
- case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String():
+ switch tvStr.Type {
+ case commontypes.LinkToken:
pub := solana.MustPublicKeyFromBase58(address)
state.LinkToken = pub
- case deployment.NewTypeAndVersion(SolCcipRouter, deployment.Version1_0_0).String():
+ case Router:
+ pub := solana.MustPublicKeyFromBase58(address)
+ state.Router = pub
+ routerStatePDA, _, err := solState.FindStatePDA(state.Router)
+ if err != nil {
+ return state, err
+ }
+ state.RouterStatePDA = routerStatePDA
+ routerConfigPDA, _, err := solState.FindConfigPDA(state.Router)
+ if err != nil {
+ return state, err
+ }
+ state.RouterConfigPDA = routerConfigPDA
+ case AddressLookupTable:
+ pub := solana.MustPublicKeyFromBase58(address)
+ state.AddressLookupTable = pub
+ case Receiver:
pub := solana.MustPublicKeyFromBase58(address)
- state.SolCcipRouter = pub
+ state.Receiver = pub
+ case SPL2022Tokens:
+ pub := solana.MustPublicKeyFromBase58(address)
+ spl2022Tokens = append(spl2022Tokens, pub)
+ case TokenPool:
+ pub := solana.MustPublicKeyFromBase58(address)
+ state.TokenPool = pub
+ case RemoteSource:
+ pub := solana.MustPublicKeyFromBase58(address)
+ // Labels should only have one entry
+ for selStr := range tvStr.Labels {
+ selector, err := strconv.ParseUint(selStr, 10, 64)
+ if err != nil {
+ return state, err
+ }
+ state.SourceChainStatePDAs[selector] = pub
+ }
+ case RemoteDest:
+ pub := solana.MustPublicKeyFromBase58(address)
+ // Labels should only have one entry
+ for selStr := range tvStr.Labels {
+ selector, err := strconv.ParseUint(selStr, 10, 64)
+ if err != nil {
+ return state, err
+ }
+ state.DestChainStatePDAs[selector] = pub
+ }
default:
return state, fmt.Errorf("unknown contract %s", tvStr)
}
}
+ state.WSOL = solana.SolMint
+ state.SPL2022Tokens = spl2022Tokens
return state, nil
}
-
-// GetRouterConfigPDA returns the PDA for the "config" account.
-func GetRouterConfigPDA(ccipRouterProgramID solana.PublicKey) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{[]byte("config")},
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetRouterStatePDA returns the PDA for the "state" account.
-func GetRouterStatePDA(ccipRouterProgramID solana.PublicKey) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{[]byte("state")},
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetExternalExecutionConfigPDA returns the PDA for the "external_execution_config" account.
-func GetExternalExecutionConfigPDA(ccipRouterProgramID solana.PublicKey) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{[]byte("external_execution_config")},
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetExternalTokenPoolsSignerPDA returns the PDA for the "external_token_pools_signer" account.
-func GetExternalTokenPoolsSignerPDA(ccipRouterProgramID solana.PublicKey) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{[]byte("external_token_pools_signer")},
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetSolanaSourceChainStatePDA returns the PDA for the "source_chain_state" account for Solana.
-func GetSolanaSourceChainStatePDA(ccipRouterProgramID solana.PublicKey, solanaChainSelector uint64) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{
- []byte("source_chain_state"),
- binary.LittleEndian.AppendUint64([]byte{}, solanaChainSelector),
- },
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetSolanaDestChainStatePDA returns the PDA for the "dest_chain_state" account for Solana.
-func GetSolanaDestChainStatePDA(ccipRouterProgramID solana.PublicKey, solanaChainSelector uint64) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{
- []byte("dest_chain_state"),
- binary.LittleEndian.AppendUint64([]byte{}, solanaChainSelector),
- },
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetEvmSourceChainStatePDA returns the PDA for the "source_chain_state" account for EVM.
-func GetEvmSourceChainStatePDA(ccipRouterProgramID solana.PublicKey, evmChainSelector uint64) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{
- []byte("source_chain_state"),
- binary.LittleEndian.AppendUint64([]byte{}, evmChainSelector),
- },
- ccipRouterProgramID,
- )
- return pda
-}
-
-// GetEvmDestChainStatePDA returns the PDA for the "dest_chain_state" account for EVM.
-func GetEvmDestChainStatePDA(ccipRouterProgramID solana.PublicKey, evmChainSelector uint64) solana.PublicKey {
- pda, _, _ := solana.FindProgramAddress(
- [][]byte{
- []byte("dest_chain_state"),
- binary.LittleEndian.AppendUint64([]byte{}, evmChainSelector),
- },
- ccipRouterProgramID,
- )
- return pda
-}
diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go
index c353b43ce9b..739333b720b 100644
--- a/deployment/ccip/changeset/state.go
+++ b/deployment/ccip/changeset/state.go
@@ -34,32 +34,33 @@ import (
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_0"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_2"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5_1"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_6"
commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset"
commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0"
"github.com/smartcontractkit/chainlink/deployment/helpers"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3"
+ chain_selectors "github.com/smartcontractkit/chain-selectors"
"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"
- capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
-
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract"
"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/registry_module_owner_custom"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home"
"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"
+ capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
)
var (
@@ -184,6 +185,42 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) {
}
chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView
}
+ for tokenSymbol, versionToPool := range c.BurnMintTokenPools {
+ for _, tokenPool := range versionToPool {
+ tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool)
+ if err != nil {
+ return chainView, errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String())
+ }
+ chainView.BurnMintTokenPool = helpers.AddValueToNestedMap(chainView.BurnMintTokenPool, tokenPool.Address().Hex(), string(tokenSymbol), tokenPoolView)
+ }
+ }
+ for tokenSymbol, versionToPool := range c.BurnWithFromMintTokenPools {
+ for _, tokenPool := range versionToPool {
+ tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool)
+ if err != nil {
+ return chainView, errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String())
+ }
+ chainView.BurnMintTokenPool = helpers.AddValueToNestedMap(chainView.BurnMintTokenPool, tokenPool.Address().Hex(), string(tokenSymbol), tokenPoolView)
+ }
+ }
+ for tokenSymbol, versionToPool := range c.BurnFromMintTokenPools {
+ for _, tokenPool := range versionToPool {
+ tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool)
+ if err != nil {
+ return chainView, errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String())
+ }
+ chainView.BurnMintTokenPool = helpers.AddValueToNestedMap(chainView.BurnMintTokenPool, tokenPool.Address().Hex(), string(tokenSymbol), tokenPoolView)
+ }
+ }
+ for tokenSymbol, versionToPool := range c.LockReleaseTokenPools {
+ for _, tokenPool := range versionToPool {
+ tokenPoolView, err := v1_5_1.GenerateLockReleaseTokenPoolView(tokenPool)
+ if err != nil {
+ return chainView, errors.Wrapf(err, "failed to generate lock release token pool view for %s", tokenPool.Address().String())
+ }
+ chainView.LockReleaseTokenPool = helpers.AddValueToNestedMap(chainView.LockReleaseTokenPool, tokenPool.Address().Hex(), string(tokenSymbol), tokenPoolView)
+ }
+ }
if c.NonceManager != nil {
nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager)
if err != nil {
@@ -416,6 +453,25 @@ func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, erro
return m, nil
}
+func (s CCIPOnChainState) GetOffRampAddress(chainSelector uint64) ([]byte, error) {
+ family, err := chain_selectors.GetSelectorFamily(chainSelector)
+ if err != nil {
+ return nil, err
+ }
+
+ var offRampAddress []byte
+ switch family {
+ case chain_selectors.FamilyEVM:
+ offRampAddress = s.Chains[chainSelector].OffRamp.Address().Bytes()
+ case chain_selectors.FamilySolana:
+ offRampAddress = s.SolChains[chainSelector].Router.Bytes()
+ default:
+ return nil, fmt.Errorf("unsupported chain family %s", family)
+ }
+
+ return offRampAddress, nil
+}
+
func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) {
solState, err := LoadOnchainStateSolana(e)
if err != nil {
@@ -750,3 +806,57 @@ func LoadChainState(ctx context.Context, chain deployment.Chain, addresses map[s
}
return state, nil
}
+
+func (s CCIPOnChainState) ValidateOffRamp(chainSelector uint64) error {
+ family, err := chain_selectors.GetSelectorFamily(chainSelector)
+ if err != nil {
+ return err
+ }
+ switch family {
+ case chain_selectors.FamilyEVM:
+ chainState, exists := s.Chains[chainSelector]
+ if !exists {
+ return fmt.Errorf("chain %d does not exist", chainSelector)
+ }
+ if chainState.OffRamp == nil {
+ // should not be possible, but a defensive check.
+ return fmt.Errorf("OffRamp contract does not exist on chain %d", chainSelector)
+ }
+ case chain_selectors.FamilySolana:
+ chainState, exists := s.SolChains[chainSelector]
+ if !exists {
+ return fmt.Errorf("chain %d does not exist", chainSelector)
+ }
+ if chainState.Router.IsZero() {
+ // should not be possible, but a defensive check.
+ return fmt.Errorf("CCIP router contract does not exist on chain %d", chainSelector)
+ }
+ default:
+ return fmt.Errorf("unknown chain family %s", family)
+ }
+ return nil
+}
+
+func ValidateChain(env deployment.Environment, state CCIPOnChainState, chainSel uint64, checkMcms bool) error {
+ err := deployment.IsValidChainSelector(chainSel)
+ if err != nil {
+ return fmt.Errorf("is not valid chain selector %d: %w", chainSel, err)
+ }
+ chain, ok := env.Chains[chainSel]
+ if !ok {
+ return fmt.Errorf("chain with selector %d does not exist in environment", chainSel)
+ }
+ chainState, ok := state.Chains[chainSel]
+ if !ok {
+ return fmt.Errorf("%s does not exist in state", chain)
+ }
+ if checkMcms {
+ if chainState.Timelock == nil {
+ return fmt.Errorf("missing timelock on %s", chain)
+ }
+ if chainState.ProposerMcm == nil {
+ return fmt.Errorf("missing proposerMcm on %s", chain)
+ }
+ }
+ return nil
+}
diff --git a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go
new file mode 100644
index 00000000000..36b03e576de
--- /dev/null
+++ b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go
@@ -0,0 +1,202 @@
+package messagingtest
+
+import (
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ chain_selectors "github.com/smartcontractkit/chain-selectors"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink/deployment"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
+)
+
+// Use this when testhelpers.DeployedEnv is available (usually in ephemeral test environments).
+func NewTestSetupWithDeployedEnv(
+ t *testing.T,
+ depEnv testhelpers.DeployedEnv,
+ onchainState changeset.CCIPOnChainState,
+ sourceChain,
+ destChain uint64,
+ sender []byte,
+ testRouter,
+ validateResp bool,
+) TestSetup {
+ return TestSetup{
+ T: t,
+ Sender: sender,
+ Env: depEnv.Env,
+ DeployedEnv: depEnv,
+ OnchainState: onchainState,
+ SourceChain: sourceChain,
+ DestChain: destChain,
+ TestRouter: testRouter,
+ ValidateResp: validateResp,
+ }
+}
+
+// Use this when testhelpers.DeployedEnv is not available (usually in long-running test environments like staging).
+func NewTestSetup(
+ t *testing.T,
+ env deployment.Environment,
+ onchainState changeset.CCIPOnChainState,
+ sourceChain,
+ destChain uint64,
+ sender []byte,
+ testRouter,
+ validateResp bool,
+) TestSetup {
+ return TestSetup{
+ T: t,
+ Sender: sender,
+ Env: env,
+ // no DeployedEnv
+ OnchainState: onchainState,
+ SourceChain: sourceChain,
+ DestChain: destChain,
+ TestRouter: testRouter,
+ ValidateResp: validateResp,
+ }
+}
+
+type TestSetup struct {
+ T *testing.T
+ Sender []byte
+ Env deployment.Environment
+ DeployedEnv testhelpers.DeployedEnv
+ OnchainState changeset.CCIPOnChainState
+ SourceChain uint64
+ DestChain uint64
+ TestRouter bool
+ ValidateResp bool
+}
+
+type TestCase struct {
+ TestSetup
+ Replayed bool
+ Nonce uint64
+ Receiver common.Address
+ MsgData []byte
+ ExtraArgs []byte
+ ExpectedExecutionState int
+ ExtraAssertions []func(t *testing.T)
+}
+
+type TestCaseOutput struct {
+ Replayed bool
+ Nonce uint64
+ MsgSentEvent *onramp.OnRampCCIPMessageSent
+}
+
+func sleepAndReplay(t *testing.T, e testhelpers.DeployedEnv, sourceChain, destChain uint64) {
+ time.Sleep(30 * time.Second)
+ replayBlocks := make(map[uint64]uint64)
+ replayBlocks[sourceChain] = 1
+ replayBlocks[destChain] = 1
+
+ testhelpers.ReplayLogs(t, e.Env.Offchain, replayBlocks)
+}
+
+func getLatestNonce(tc TestCase) uint64 {
+ family, err := chain_selectors.GetSelectorFamily(tc.DestChain)
+ require.NoError(tc.T, err)
+
+ var latestNonce uint64
+ switch family {
+ case chain_selectors.FamilyEVM:
+ latestNonce, err = tc.OnchainState.Chains[tc.DestChain].NonceManager.GetInboundNonce(&bind.CallOpts{
+ Context: tests.Context(tc.T),
+ }, tc.SourceChain, tc.Sender)
+ require.NoError(tc.T, err)
+ case chain_selectors.FamilySolana:
+ // var nonceCounterAccount ccip_router.Nonce
+ // err = common.GetAccountDataBorshInto(ctx, solanaGoClient, nonceEvmPDA, config.DefaultCommitment, &nonceCounterAccount)
+ // require.NoError(t, err, "failed to get account info")
+ // require.Equal(t, uint64(1), nonceCounterAccount.Counter)
+ }
+ return latestNonce
+}
+
+// Run runs a messaging test case.
+func Run(tc TestCase) (out TestCaseOutput) {
+ // check latest nonce
+ latestNonce := getLatestNonce(tc)
+ require.Equal(tc.T, tc.Nonce, latestNonce)
+
+ startBlocks := make(map[uint64]*uint64)
+ msgSentEvent := testhelpers.TestSendRequest(
+ tc.T,
+ tc.Env,
+ tc.OnchainState,
+ tc.SourceChain,
+ tc.DestChain,
+ tc.TestRouter,
+ router.ClientEVM2AnyMessage{
+ Receiver: common.LeftPadBytes(tc.Receiver.Bytes(), 32),
+ Data: tc.MsgData,
+ TokenAmounts: nil,
+ FeeToken: common.HexToAddress("0x0"),
+ ExtraArgs: tc.ExtraArgs,
+ })
+ expectedSeqNum := map[testhelpers.SourceDestPair]uint64{
+ {
+ SourceChainSelector: tc.SourceChain,
+ DestChainSelector: tc.DestChain,
+ }: msgSentEvent.SequenceNumber,
+ }
+ expectedSeqNumExec := map[testhelpers.SourceDestPair][]uint64{
+ {
+ SourceChainSelector: tc.SourceChain,
+ DestChainSelector: tc.DestChain,
+ }: {msgSentEvent.SequenceNumber},
+ }
+ out.MsgSentEvent = msgSentEvent
+
+ // hack
+ if !tc.Replayed {
+ require.NotNil(tc.T, tc.DeployedEnv)
+ sleepAndReplay(tc.T, tc.DeployedEnv, tc.SourceChain, tc.DestChain)
+ out.Replayed = true
+ }
+
+ if tc.ValidateResp {
+ testhelpers.ConfirmCommitForAllWithExpectedSeqNums(tc.T, tc.Env, tc.OnchainState, expectedSeqNum, startBlocks)
+ execStates := testhelpers.ConfirmExecWithSeqNrsForAll(tc.T, tc.Env, tc.OnchainState, expectedSeqNumExec, startBlocks)
+
+ require.Equalf(
+ tc.T,
+ tc.ExpectedExecutionState,
+ execStates[testhelpers.SourceDestPair{
+ SourceChainSelector: tc.SourceChain,
+ DestChainSelector: tc.DestChain,
+ }][msgSentEvent.SequenceNumber],
+ "wrong execution state for seq nr %d, expected %d, got %d",
+ msgSentEvent.SequenceNumber,
+ tc.ExpectedExecutionState,
+ execStates[testhelpers.SourceDestPair{
+ SourceChainSelector: tc.SourceChain,
+ DestChainSelector: tc.DestChain,
+ }][msgSentEvent.SequenceNumber],
+ )
+
+ // check the sender latestNonce on the dest, should be incremented
+ latestNonce = getLatestNonce(tc)
+ require.Equal(tc.T, tc.Nonce+1, latestNonce)
+ out.Nonce = latestNonce
+ tc.T.Logf("confirmed nonce bump for sender %x, latestNonce %d", tc.Sender, latestNonce)
+
+ for _, assertion := range tc.ExtraAssertions {
+ assertion(tc.T)
+ }
+ } else {
+ tc.T.Logf("skipping validation of sent message")
+ }
+
+ return
+}
diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go
index 152c41c82f1..991d67a2e26 100644
--- a/deployment/ccip/changeset/testhelpers/test_environment.go
+++ b/deployment/ccip/changeset/testhelpers/test_environment.go
@@ -9,27 +9,29 @@ import (
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
- "github.com/smartcontractkit/chainlink-ccip/chainconfig"
- cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
- "github.com/smartcontractkit/chainlink-ccip/pluginconfig"
- commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
- "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
- "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
+ "github.com/smartcontractkit/chainlink-ccip/chainconfig"
+ cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
+ "github.com/smartcontractkit/chainlink-ccip/pluginconfig"
+ commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config"
"github.com/smartcontractkit/chainlink/deployment"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals"
+ changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana"
commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
+ "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types"
)
type EnvType string
@@ -48,6 +50,7 @@ type TestConfigs struct {
PrerequisiteDeploymentOnly bool
V1_5Cfg changeset.V1_5DeploymentConfig
Chains int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input
+ SolChains int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input
ChainIDs []uint64 // only used in memory mode, for docker mode, this is determined by the integration-test config toml input
NumOfUsersPerChain int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input
Nodes int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input
@@ -55,6 +58,7 @@ type TestConfigs struct {
IsUSDC bool
IsUSDCAttestationMissing bool
IsMultiCall3 bool
+ IsStaticLink bool
OCRConfigOverride func(*changeset.CCIPOCRParams)
RMNEnabled bool
NumOfRMNNodes int
@@ -117,6 +121,12 @@ func WithMultiCall3() TestOps {
}
}
+func WithStaticLink() TestOps {
+ return func(testCfg *TestConfigs) {
+ testCfg.IsStaticLink = true
+ }
+}
+
func WithPrerequisiteDeploymentOnly(v1_5Cfg *changeset.V1_5DeploymentConfig) TestOps {
return func(testCfg *TestConfigs) {
testCfg.PrerequisiteDeploymentOnly = true
@@ -177,6 +187,12 @@ func WithNumOfChains(numChains int) TestOps {
}
}
+func WithSolChains(numChains int) TestOps {
+ return func(testCfg *TestConfigs) {
+ testCfg.SolChains = numChains
+ }
+}
+
func WithNumOfUsersPerChain(numUsers int) TestOps {
return func(testCfg *TestConfigs) {
testCfg.NumOfUsersPerChain = numUsers
@@ -251,6 +267,7 @@ type MemoryEnvironment struct {
DeployedEnv
TestConfig *TestConfigs
Chains map[uint64]deployment.Chain
+ SolChains map[uint64]deployment.SolChain
}
func (m *MemoryEnvironment) TestConfigs() *TestConfigs {
@@ -284,13 +301,16 @@ func (m *MemoryEnvironment) StartChains(t *testing.T) {
} else {
chains, users = memory.NewMemoryChains(t, tc.Chains, tc.NumOfUsersPerChain)
}
+
m.Chains = chains
+ m.SolChains = memory.NewMemoryChainsSol(t, tc.SolChains)
homeChainSel, feedSel := allocateCCIPChainSelectors(chains)
replayBlocks, err := LatestBlocksByChain(ctx, chains)
require.NoError(t, err)
m.DeployedEnv = DeployedEnv{
Env: deployment.Environment{
- Chains: m.Chains,
+ Chains: m.Chains,
+ SolChains: m.SolChains,
},
HomeChainSel: homeChainSel,
FeedChainSel: feedSel,
@@ -303,7 +323,7 @@ func (m *MemoryEnvironment) StartNodes(t *testing.T, crConfig deployment.Capabil
require.NotNil(t, m.Chains, "start chains first, chains are empty")
require.NotNil(t, m.DeployedEnv, "start chains and initiate deployed env first before starting nodes")
tc := m.TestConfig
- nodes := memory.NewNodes(t, zapcore.InfoLevel, m.Chains, tc.Nodes, tc.Bootstraps, crConfig)
+ nodes := memory.NewNodes(t, zapcore.InfoLevel, m.Chains, m.SolChains, tc.Nodes, tc.Bootstraps, crConfig)
ctx := testcontext.Get(t)
lggr := logger.Test(t)
for _, node := range nodes {
@@ -312,7 +332,7 @@ func (m *MemoryEnvironment) StartNodes(t *testing.T, crConfig deployment.Capabil
require.NoError(t, node.App.Stop())
})
}
- m.DeployedEnv.Env = memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, m.Chains, nodes)
+ m.DeployedEnv.Env = memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, m.Chains, m.SolChains, nodes)
}
func (m *MemoryEnvironment) MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string {
@@ -389,14 +409,19 @@ func NewEnvironmentWithPrerequisitesContracts(t *testing.T, tEnv TestEnvironment
var err error
tc := tEnv.TestConfigs()
e := NewEnvironment(t, tEnv)
- allChains := e.Env.AllChainSelectors()
-
+ evmChains := e.Env.AllChainSelectors()
+ solChains := e.Env.AllChainSelectorsSolana()
+ //nolint:gocritic // we need to segregate EVM and Solana chains
+ allChains := append(evmChains, solChains...)
+ if len(solChains) > 0 {
+ SavePreloadedSolAddresses(t, e.Env, solChains[0])
+ }
mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig)
for _, c := range e.Env.AllChainSelectors() {
mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t)
}
prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0)
- for _, chain := range allChains {
+ for _, chain := range evmChains {
var opts []changeset.PrerequisiteOpt
if tc != nil {
if tc.IsUSDC {
@@ -414,12 +439,18 @@ func NewEnvironmentWithPrerequisitesContracts(t *testing.T, tEnv TestEnvironment
Opts: opts,
})
}
-
- e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
- {
- Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
+ deployLinkApp := commonchangeset.ChangesetApplication{
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
+ Config: allChains,
+ }
+ if tc.IsStaticLink {
+ deployLinkApp = commonchangeset.ChangesetApplication{
+ Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployStaticLinkToken),
Config: allChains,
- },
+ }
+ }
+ e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
+ deployLinkApp,
{
Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset),
Config: changeset.DeployPrerequisiteConfig{
@@ -454,58 +485,26 @@ func NewEnvironment(t *testing.T, tEnv TestEnvironment) DeployedEnv {
func NewEnvironmentWithJobsAndContracts(t *testing.T, tEnv TestEnvironment) DeployedEnv {
var err error
- tc := tEnv.TestConfigs()
- e := NewEnvironment(t, tEnv)
- allChains := e.Env.AllChainSelectors()
+ e := NewEnvironmentWithPrerequisitesContracts(t, tEnv)
+ evmChains := e.Env.AllChainSelectors()
+ solChains := e.Env.AllChainSelectorsSolana()
+ //nolint:gocritic // we need to segregate EVM and Solana chains
+ allChains := append(evmChains, solChains...)
mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig)
for _, c := range e.Env.AllChainSelectors() {
mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t)
}
- prereqCfg := make([]changeset.DeployPrerequisiteConfigPerChain, 0)
- for _, chain := range allChains {
- var opts []changeset.PrerequisiteOpt
- if tc != nil {
- if tc.IsUSDC {
- opts = append(opts, changeset.WithUSDCEnabled())
- }
- if tc.IsMultiCall3 {
- opts = append(opts, changeset.WithMultiCall3Enabled())
- }
- }
- prereqCfg = append(prereqCfg, changeset.DeployPrerequisiteConfigPerChain{
- ChainSelector: chain,
- Opts: opts,
- })
- }
- // Need to deploy prerequisites first so that we can form the USDC config
- // no proposals to be made, timelock can be passed as nil here
- e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
- {
- Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken),
- Config: allChains,
- },
- {
- Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisitesChangeset),
- Config: changeset.DeployPrerequisiteConfig{
- Configs: prereqCfg,
- },
- },
- {
- Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock),
- Config: mcmsCfg,
- },
- })
- require.NoError(t, err)
tEnv.UpdateDeployedEnvironment(e)
- e = AddCCIPContractsToEnvironment(t, e.Env.AllChainSelectors(), tEnv, false)
+
+ e = AddCCIPContractsToEnvironment(t, allChains, tEnv, false)
// now we update RMNProxy to point to RMNRemote
e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(changeset.SetRMNRemoteOnRMNProxyChangeset),
Config: changeset.SetRMNRemoteOnRMNProxyConfig{
- ChainSelectors: allChains,
+ ChainSelectors: evmChains,
},
},
})
@@ -523,12 +522,28 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
// no proposals to be made, timelock can be passed as nil here
var apps []commonchangeset.ChangesetApplication
allContractParams := make(map[uint64]changeset.ChainContractParams)
+
for _, chain := range allChains {
allContractParams[chain] = changeset.ChainContractParams{
FeeQuoterParams: changeset.DefaultFeeQuoterParams(),
OffRampParams: changeset.DefaultOffRampParams(),
}
}
+
+ evmChains := []uint64{}
+ for _, chain := range allChains {
+ if _, ok := e.Env.Chains[chain]; ok {
+ evmChains = append(evmChains, chain)
+ }
+ }
+
+ solChains := []uint64{}
+ for _, chain := range allChains {
+ if _, ok := e.Env.SolChains[chain]; ok {
+ solChains = append(solChains, chain)
+ }
+ }
+
apps = append(apps, []commonchangeset.ChangesetApplication{
{
Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChainChangeset),
@@ -556,7 +571,11 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
state, err := changeset.LoadOnchainState(e.Env)
require.NoError(t, err)
// Assert link present
- require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken)
+ if tc.IsStaticLink {
+ require.NotNil(t, state.Chains[e.FeedChainSel].StaticLinkToken)
+ } else {
+ require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken)
+ }
require.NotNil(t, state.Chains[e.FeedChainSel].Weth9)
tokenConfig := changeset.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds)
@@ -564,7 +583,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
if tc.IsUSDC {
endpoint := tEnv.MockUSDCAttestationServer(t, tc.IsUSDCAttestationMissing)
cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig)
- for _, usdcChain := range allChains {
+ for _, usdcChain := range evmChains {
require.NotNil(t, state.Chains[usdcChain].MockUSDCTokenMessenger)
require.NotNil(t, state.Chains[usdcChain].MockUSDCTransmitter)
require.NotNil(t, state.Chains[usdcChain].USDCTokenPool)
@@ -583,18 +602,29 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond),
}})
}
- // Build the per chain config.
- ocrConfigs := make(map[uint64]changeset.CCIPOCRParams)
- chainConfigs := make(map[uint64]changeset.ChainConfig)
+
timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts)
+ timelockContractsPerChain[e.HomeChainSel] = &proposalutils.TimelockExecutionContracts{
+ Timelock: state.Chains[e.HomeChainSel].Timelock,
+ CallProxy: state.Chains[e.HomeChainSel].CallProxy,
+ }
nodeInfo, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain)
require.NoError(t, err)
- for _, chain := range allChains {
+ // Build the per chain config.
+ chainConfigs := make(map[uint64]changeset.ChainConfig)
+ ocrConfigs := make(map[uint64]changeset.CCIPOCRParams)
+ for _, chain := range evmChains {
timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{
Timelock: state.Chains[chain].Timelock,
CallProxy: state.Chains[chain].CallProxy,
}
- tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9)
+ var linkTokenAddr common.Address
+ if tc.IsStaticLink {
+ linkTokenAddr = state.Chains[chain].StaticLinkToken.Address()
+ } else {
+ linkTokenAddr = state.Chains[chain].LinkToken.Address()
+ }
+ tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, linkTokenAddr, state.Chains[chain].Weth9.Address())
ocrOverride := tc.OCRConfigOverride
if tc.RMNEnabled {
ocrOverride = func(ocrParams *changeset.CCIPOCRParams) {
@@ -620,10 +650,28 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
},
}
}
- timelockContractsPerChain[e.HomeChainSel] = &proposalutils.TimelockExecutionContracts{
- Timelock: state.Chains[e.HomeChainSel].Timelock,
- CallProxy: state.Chains[e.HomeChainSel].CallProxy,
+
+ for _, chain := range solChains {
+ ocrOverride := tc.OCRConfigOverride
+ ocrParams := changeset.DeriveCCIPOCRParams(
+ // TODO: tokenInfo is nil for solana
+ changeset.WithDefaultCommitOffChainConfig(e.FeedChainSel, nil),
+ changeset.WithDefaultExecuteOffChainConfig(tokenDataProviders),
+ changeset.WithOCRParamOverride(ocrOverride),
+ )
+ ocrConfigs[chain] = ocrParams
+ chainConfigs[chain] = changeset.ChainConfig{
+ Readers: nodeInfo.NonBootstraps().PeerIDs(),
+ // #nosec G115 - Overflow is not a concern in this test scenario
+ FChain: uint8(len(nodeInfo.NonBootstraps().PeerIDs()) / 3),
+ EncodableChainConfig: chainconfig.ChainConfig{
+ GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.GasPriceDeviationPPB)},
+ DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.DAGasPriceDeviationPPB)},
+ OptimisticConfirmations: globals.OptimisticConfirmations,
+ },
+ }
}
+
// Apply second set of changesets to configure the CCIP contracts.
var mcmsConfig *changeset.MCMSConfig
if mcmsEnabled {
@@ -647,6 +695,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
Config: changeset.AddDonAndSetCandidateChangesetConfig{
SetCandidateConfigBase: changeset.SetCandidateConfigBase{
HomeChainSelector: e.HomeChainSel,
+ // TODO: we dont know what this means for solana
FeedChainSelector: e.FeedChainSel,
MCMS: mcmsConfig,
},
@@ -662,6 +711,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
Config: changeset.SetCandidateChangesetConfig{
SetCandidateConfigBase: changeset.SetCandidateConfigBase{
HomeChainSelector: e.HomeChainSel,
+ // TODO: we dont know what this means for solana
FeedChainSelector: e.FeedChainSel,
MCMS: mcmsConfig,
},
@@ -696,7 +746,16 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
Changeset: commonchangeset.WrapChangeSet(changeset.SetOCR3OffRampChangeset),
Config: changeset.SetOCR3OffRampConfig{
HomeChainSel: e.HomeChainSel,
- RemoteChainSels: allChains,
+ RemoteChainSels: evmChains,
+ CCIPHomeConfigType: globals.ConfigTypeActive,
+ },
+ },
+ {
+ // Enable the OCR config on the remote chains.
+ Changeset: commonchangeset.WrapChangeSet(changeset_solana.SetOCR3ConfigSolana),
+ Config: changeset.SetOCR3OffRampConfig{
+ HomeChainSel: e.HomeChainSel,
+ RemoteChainSels: solChains,
CCIPHomeConfigType: globals.ConfigTypeActive,
},
},
@@ -714,8 +773,12 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
require.NotNil(t, state.Chains[e.HomeChainSel].CapabilityRegistry)
require.NotNil(t, state.Chains[e.HomeChainSel].CCIPHome)
require.NotNil(t, state.Chains[e.HomeChainSel].RMNHome)
- for _, chain := range allChains {
- require.NotNil(t, state.Chains[chain].LinkToken)
+ for _, chain := range evmChains {
+ if tc.IsStaticLink {
+ require.NotNil(t, state.Chains[chain].StaticLinkToken)
+ } else {
+ require.NotNil(t, state.Chains[chain].LinkToken)
+ }
require.NotNil(t, state.Chains[chain].Weth9)
require.NotNil(t, state.Chains[chain].TokenAdminRegistry)
require.NotNil(t, state.Chains[chain].RegistryModule)
@@ -727,6 +790,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn
require.NotNil(t, state.Chains[chain].OffRamp)
require.NotNil(t, state.Chains[chain].OnRamp)
}
+ ValidateSolanaState(t, e.Env, solChains)
tEnv.UpdateDeployedEnvironment(e)
return e
}
diff --git a/deployment/ccip/changeset/testhelpers/test_helpers.go b/deployment/ccip/changeset/testhelpers/test_helpers.go
index 1be54d53684..75d190ae3f0 100644
--- a/deployment/ccip/changeset/testhelpers/test_helpers.go
+++ b/deployment/ccip/changeset/testhelpers/test_helpers.go
@@ -2,6 +2,7 @@ package testhelpers
import (
"context"
+ "encoding/json"
"fmt"
"math/big"
"net/http"
@@ -19,6 +20,7 @@ import (
"github.com/pkg/errors"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana"
commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
@@ -29,6 +31,7 @@ import (
chainsel "github.com/smartcontractkit/chain-selectors"
"go.uber.org/multierr"
+ "go.uber.org/zap/zapcore"
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"
@@ -43,6 +46,9 @@ import (
"github.com/smartcontractkit/chainlink/deployment/environment/devenv"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
+ solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router"
+ solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state"
+
solTestConfig "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
@@ -53,6 +59,10 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/mock_v3_aggregator_contract"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
+
+ "github.com/gagliardetto/solana-go"
+
+ "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_receiver"
)
const (
@@ -409,7 +419,16 @@ func AddLane(
fqCfg fee_quoter.FeeQuoterDestChainConfig,
) {
var err error
- e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{
+
+ // from family
+ fromFamily, _ := chainsel.GetSelectorFamily(from)
+ toFamily, _ := chainsel.GetSelectorFamily(to)
+
+ if fromFamily != chainsel.FamilyEVM {
+ t.Fatalf("from family is not evm, %s", fromFamily)
+ }
+
+ changesets := []commoncs.ChangesetApplication{
{
Changeset: commoncs.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset),
Config: changeset.UpdateOnRampDestsConfig{
@@ -445,40 +464,128 @@ func AddLane(
},
},
},
- {
- Changeset: commoncs.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset),
- Config: changeset.UpdateOffRampSourcesConfig{
- UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{
- to: {
+ }
+
+ require.NoError(t, err)
+
+ switch toFamily {
+ case chainsel.FamilyEVM:
+ evmChangesets := []commoncs.ChangesetApplication{
+ {
+ Changeset: commoncs.WrapChangeSet(changeset.UpdateOffRampSourcesChangeset),
+ Config: changeset.UpdateOffRampSourcesConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{
+ to: {
+ from: {
+ IsEnabled: true,
+ TestRouter: isTestRouter,
+ },
+ },
+ },
+ },
+ },
+ {
+ Changeset: commoncs.WrapChangeSet(changeset.UpdateRouterRampsChangeset),
+ Config: changeset.UpdateRouterRampsConfig{
+ TestRouter: isTestRouter,
+ UpdatesByChain: map[uint64]changeset.RouterUpdates{
+ // onRamp update on source chain
from: {
- IsEnabled: true,
- TestRouter: isTestRouter,
+ OnRampUpdates: map[uint64]bool{
+ to: true,
+ },
+ },
+ // offramp update on dest chain
+ to: {
+ OffRampUpdates: map[uint64]bool{
+ from: true,
+ },
},
},
},
},
- },
+ }
+ changesets = append(changesets, evmChangesets...)
+ case chainsel.FamilySolana:
+ value := [28]uint8{}
+ bigNum, ok := new(big.Int).SetString("19816680000000000000", 10)
+ require.True(t, ok)
+ bigNum.FillBytes(value[:])
+ solanaChangesets := []commoncs.ChangesetApplication{
+ {
+ Changeset: commoncs.WrapChangeSet(changeset_solana.AddRemoteChainToSolana),
+ Config: changeset_solana.AddRemoteChainToSolanaConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset_solana.RemoteChainConfigSolana{
+ to: {
+ from: {
+ EnabledAsSource: true,
+ DestinationConfig: solRouter.DestChainConfig{
+ IsEnabled: true,
+ DefaultTxGasLimit: 200000,
+ MaxPerMsgGasLimit: 3000000,
+ MaxDataBytes: 30000,
+ MaxNumberOfTokensPerMsg: 5,
+ DefaultTokenDestGasOverhead: 5000,
+ // bytes4(keccak256("CCIP ChainFamilySelector EVM"))
+ // TODO: do a similar test for other chain families
+ ChainFamilySelector: [4]uint8{40, 18, 213, 44},
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ changesets = append(changesets, solanaChangesets...)
+ }
+
+ e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), changesets)
+ require.NoError(t, err)
+}
+
+// RemoveLane removes a lane between the source and destination chains in the deployed environment.
+func RemoveLane(t *testing.T, e *DeployedEnv, src, dest uint64, isTestRouter bool) {
+ var err error
+ apps := []commoncs.ChangesetApplication{
{
Changeset: commoncs.WrapChangeSet(changeset.UpdateRouterRampsChangeset),
Config: changeset.UpdateRouterRampsConfig{
- TestRouter: isTestRouter,
UpdatesByChain: map[uint64]changeset.RouterUpdates{
// onRamp update on source chain
- from: {
+ src: {
OnRampUpdates: map[uint64]bool{
- to: true,
+ dest: false,
},
},
- // offramp update on dest chain
- to: {
- OffRampUpdates: map[uint64]bool{
- from: true,
+ },
+ },
+ },
+ {
+ Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterDestsChangeset),
+ Config: changeset.UpdateFeeQuoterDestsConfig{
+ UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{
+ src: {
+ dest: changeset.DefaultFeeQuoterDestChainConfig(false),
+ },
+ },
+ },
+ },
+ {
+ Changeset: commoncs.WrapChangeSet(changeset.UpdateOnRampsDestsChangeset),
+ Config: changeset.UpdateOnRampDestsConfig{
+ UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{
+ src: {
+ dest: {
+ IsEnabled: false,
+ TestRouter: isTestRouter,
+ AllowListEnabled: false,
},
},
},
},
},
- })
+ }
+ e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), apps)
require.NoError(t, err)
}
@@ -494,7 +601,7 @@ func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, st
}, map[common.Address]*big.Int{
stateChainFrom.LinkToken.Address(): DefaultLinkPrice,
stateChainFrom.Weth9.Address(): DefaultWethPrice,
- }, changeset.DefaultFeeQuoterDestChainConfig())
+ }, changeset.DefaultFeeQuoterDestChainConfig(true))
}
// AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain
@@ -885,10 +992,10 @@ func deployTransferTokenOneEnd(
return nil, nil, err
}
for address, v := range chainAddresses {
- if deployment.NewTypeAndVersion(changeset.ARMProxy, deployment.Version1_0_0) == v {
+ if deployment.NewTypeAndVersion(changeset.ARMProxy, deployment.Version1_0_0).Equal(v) {
rmnAddress = address
}
- if deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0) == v {
+ if deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0).Equal(v) {
routerAddress = address
}
if rmnAddress != "" && routerAddress != "" {
@@ -1250,10 +1357,65 @@ func DefaultRouterMessage(receiverAddress common.Address) router.ClientEVM2AnyMe
}
}
+// TODO: this should be linked to the solChain function
func SavePreloadedSolAddresses(t *testing.T, e deployment.Environment, solChainSelector uint64) {
- tv := deployment.NewTypeAndVersion("SolCcipRouter", deployment.Version1_0_0)
+ tv := deployment.NewTypeAndVersion(changeset.Router, deployment.Version1_0_0)
err := e.ExistingAddresses.Save(solChainSelector, solTestConfig.CcipRouterProgram.String(), tv)
require.NoError(t, err)
+ tv = deployment.NewTypeAndVersion(changeset.Receiver, deployment.Version1_0_0)
+ err = e.ExistingAddresses.Save(solChainSelector, solTestConfig.CcipLogicReceiver.String(), tv)
+ require.NoError(t, err)
+ tv = deployment.NewTypeAndVersion(changeset.TokenPool, deployment.Version1_0_0)
+ err = e.ExistingAddresses.Save(solChainSelector, solTestConfig.CcipTokenPoolProgram.String(), tv)
+ require.NoError(t, err)
+}
+
+func ValidateSolanaState(t *testing.T, e deployment.Environment, solChainSelectors []uint64) {
+ state, err := changeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err, "Failed to load Solana state")
+
+ for _, sel := range solChainSelectors {
+ // Validate chain exists in state
+ chainState, exists := state.SolChains[sel]
+ require.True(t, exists, "Chain selector %d not found in Solana state", sel)
+
+ // Validate addresses
+ require.False(t, chainState.LinkToken.IsZero(), "Link token address is zero for chain %d", sel)
+ require.False(t, chainState.Router.IsZero(), "Router address is zero for chain %d", sel)
+ require.False(t, chainState.RouterConfigPDA.IsZero(), "RouterConfigPDA is zero for chain %d", sel)
+ require.False(t, chainState.RouterStatePDA.IsZero(), "RouterStatePDA is zero for chain %d", sel)
+ require.False(t, chainState.AddressLookupTable.IsZero(), "Address lookup table is zero for chain %d", sel)
+
+ // Get router config
+ var routerConfigAccount solRouter.Config
+
+ // Check if account exists first
+ err = e.SolChains[sel].GetAccountDataBorshInto(testcontext.Get(t), chainState.RouterConfigPDA, &routerConfigAccount)
+ require.NoError(t, err, "Failed to deserialize router config for chain %d", sel)
+ }
+}
+
+func DeploySolanaCcipReceiver(t *testing.T, e deployment.Environment) {
+ state, err := changeset.LoadOnchainStateSolana(e)
+ require.NoError(t, err)
+ for solSelector, chainState := range state.SolChains {
+ ccip_receiver.SetProgramID(chainState.Receiver)
+ externalExecutionConfigPDA, _, _ := solState.FindExternalExecutionConfigPDA(chainState.Receiver)
+ instruction, ixErr := ccip_receiver.NewInitializeInstruction(
+ FindReceiverTargetAccount(chainState.Receiver),
+ externalExecutionConfigPDA,
+ e.SolChains[solSelector].DeployerKey.PublicKey(),
+ solana.SystemProgramID,
+ ).ValidateAndBuild()
+ require.NoError(t, ixErr)
+ err = e.SolChains[solSelector].Confirm([]solana.Instruction{instruction})
+ require.NoError(t, err)
+ }
+}
+
+func FindReceiverTargetAccount(receiverID solana.PublicKey) solana.PublicKey {
+ receiverTargetAccount, _, _ := solana.FindProgramAddress([][]byte{[]byte("counter")}, receiverID)
+ return receiverTargetAccount
}
func GenTestTransferOwnershipConfig(
@@ -1293,3 +1455,58 @@ func GenTestTransferOwnershipConfig(
ContractsByChain: contracts,
}
}
+
+func DeployCCIPContractsTest(t *testing.T, solChains int) {
+ e, _ := NewMemoryEnvironment(t, WithSolChains(solChains))
+ // Deploy all the CCIP contracts.
+ state, err := changeset.LoadOnchainState(e.Env)
+ require.NoError(t, err)
+ snap, err := state.View(e.Env.AllChainSelectors())
+ require.NoError(t, err)
+ if solChains > 0 {
+ DeploySolanaCcipReceiver(t, e.Env)
+ }
+
+ // 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 DeployLinkTokenTest(t *testing.T, solChains int) {
+ lggr := logger.Test(t)
+ e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
+ Chains: 1,
+ SolChains: solChains,
+ })
+ chain1 := e.AllChainSelectors()[0]
+ config := []uint64{chain1}
+ var solChain1 uint64
+ if solChains > 0 {
+ solChain1 = e.AllChainSelectorsSolana()[0]
+ config = append(config, solChain1)
+ }
+
+ e, err := commoncs.ApplyChangesets(t, e, nil, []commoncs.ChangesetApplication{
+ {
+ Changeset: commoncs.WrapChangeSet(commoncs.DeployLinkToken),
+ Config: config,
+ },
+ })
+ require.NoError(t, err)
+ addrs, err := e.ExistingAddresses.AddressesForChain(chain1)
+ require.NoError(t, err)
+ state, err := commoncs.MaybeLoadLinkTokenChainState(e.Chains[chain1], addrs)
+ require.NoError(t, err)
+ // View itself already unit tested
+ _, err = state.GenerateLinkView()
+ require.NoError(t, err)
+
+ // solana test
+ if solChains > 0 {
+ addrs, err = e.ExistingAddresses.AddressesForChain(solChain1)
+ require.NoError(t, err)
+ require.NotEmpty(t, addrs)
+ }
+}
diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/changeset/token_info.go
index 71c23b7fb44..d11ebe2758a 100644
--- a/deployment/ccip/changeset/token_info.go
+++ b/deployment/ccip/changeset/token_info.go
@@ -3,15 +3,15 @@ package changeset
import (
"math/big"
+ "github.com/ethereum/go-ethereum/common"
+
"github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
"github.com/smartcontractkit/chainlink-ccip/pluginconfig"
- "github.com/smartcontractkit/chainlink/deployment"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token"
-
"github.com/smartcontractkit/chainlink-common/pkg/logger"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9"
+ "github.com/smartcontractkit/chainlink/deployment"
+
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/aggregator_v3_interface"
)
@@ -105,15 +105,15 @@ func (tc *TokenConfig) UpsertTokenInfo(
// GetTokenInfo Adds mapping between dest chain tokens and their respective aggregators on feed chain.
func (tc *TokenConfig) GetTokenInfo(
lggr logger.Logger,
- linkToken *link_token.LinkToken,
- wethToken *weth9.WETH9,
+ linkTokenAddr,
+ wethTokenAddr common.Address,
) map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo {
tokenToAggregate := make(map[ccipocr3.UnknownEncodedAddress]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 := ccipocr3.UnknownEncodedAddress(linkToken.Address().String())
+ acc := ccipocr3.UnknownEncodedAddress(linkTokenAddr.String())
tokenToAggregate[acc] = tc.TokenSymbolToInfo[LinkSymbol]
}
@@ -121,7 +121,7 @@ func (tc *TokenConfig) GetTokenInfo(
lggr.Debugw("Weth aggregator not found, deploy without mapping link token")
} else {
lggr.Debugw("Mapping WethToken to Weth aggregator")
- acc := ccipocr3.UnknownEncodedAddress(wethToken.Address().String())
+ acc := ccipocr3.UnknownEncodedAddress(wethTokenAddr.String())
tokenToAggregate[acc] = tc.TokenSymbolToInfo[WethSymbol]
}
diff --git a/deployment/ccip/view/v1_5_1/token_pool.go b/deployment/ccip/view/v1_5_1/token_pool.go
new file mode 100644
index 00000000000..c782cb1f6cf
--- /dev/null
+++ b/deployment/ccip/view/v1_5_1/token_pool.go
@@ -0,0 +1,233 @@
+package v1_5_1
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "golang.org/x/exp/maps"
+
+ "github.com/smartcontractkit/chainlink/deployment/common/view/types"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_from_mint_token_pool"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool"
+)
+
+type TokenPoolContract interface {
+ Address() common.Address
+ Owner(opts *bind.CallOpts) (common.Address, error)
+ TypeAndVersion(*bind.CallOpts) (string, error)
+ GetToken(opts *bind.CallOpts) (common.Address, error)
+ GetSupportedChains(opts *bind.CallOpts) ([]uint64, error)
+ GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error)
+ GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error)
+ GetAllowList(opts *bind.CallOpts) ([]common.Address, error)
+ GetAllowListEnabled(opts *bind.CallOpts) (bool, error)
+}
+
+func GetCurrentInboundRateLimiterState(t TokenPoolContract, remoteChainSelector uint64) (token_pool.RateLimiterTokenBucket, error) {
+ switch v := t.(type) {
+ case *burn_mint_token_pool.BurnMintTokenPool:
+ state, err := v.GetCurrentInboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *burn_from_mint_token_pool.BurnFromMintTokenPool:
+ state, err := v.GetCurrentInboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *burn_with_from_mint_token_pool.BurnWithFromMintTokenPool:
+ state, err := v.GetCurrentInboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *lock_release_token_pool.LockReleaseTokenPool:
+ state, err := v.GetCurrentInboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *usdc_token_pool.USDCTokenPool:
+ state, err := v.GetCurrentInboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ default:
+ return token_pool.RateLimiterTokenBucket{}, fmt.Errorf("unknown type %T", t)
+ }
+}
+
+func GetCurrentOutboundRateLimiterState(t TokenPoolContract, remoteChainSelector uint64) (token_pool.RateLimiterTokenBucket, error) {
+ switch v := t.(type) {
+ case *burn_mint_token_pool.BurnMintTokenPool:
+ state, err := v.GetCurrentOutboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *burn_from_mint_token_pool.BurnFromMintTokenPool:
+ state, err := v.GetCurrentOutboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *burn_with_from_mint_token_pool.BurnWithFromMintTokenPool:
+ state, err := v.GetCurrentOutboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *lock_release_token_pool.LockReleaseTokenPool:
+ state, err := v.GetCurrentOutboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ case *usdc_token_pool.USDCTokenPool:
+ state, err := v.GetCurrentOutboundRateLimiterState(nil, remoteChainSelector)
+ return token_pool.RateLimiterTokenBucket(state), err
+ default:
+ return token_pool.RateLimiterTokenBucket{}, fmt.Errorf("unknown type %T", t)
+ }
+}
+
+type RemoteChainConfig struct {
+ // RemoteTokenAddress is the raw representation of the token address on the remote chain.
+ RemoteTokenAddress []byte
+ // RemotePoolAddresses are raw addresses of valid token pools on the remote chain.
+ RemotePoolAddresses [][]byte
+ // InboundRateLimiterConfig is the rate limiter config for inbound transfers from the remote chain.
+ InboundRateLimterConfig token_pool.RateLimiterConfig
+ // OutboundRateLimiterConfig is the rate limiter config for outbound transfers to the remote chain.
+ OutboundRateLimiterConfig token_pool.RateLimiterConfig
+}
+
+type TokenPoolView struct {
+ types.ContractMetaData
+ Token common.Address `json:"token"`
+ RemoteChainConfigs map[uint64]RemoteChainConfig `json:"remoteChainConfigs"`
+ AllowList []common.Address `json:"allowList"`
+ AllowListEnabled bool `json:"allowListEnable"`
+}
+
+type USDCTokenPoolView struct {
+ TokenPoolView
+ TokenMessenger common.Address
+ MessageTransmitter common.Address
+ LocalDomain uint32
+ ChainToDomain map[uint64]usdc_token_pool.USDCTokenPoolDomain
+}
+
+type LockReleaseTokenPoolView struct {
+ TokenPoolView
+ AcceptLiquidity bool
+ Rebalancer common.Address
+}
+
+func GenerateTokenPoolView(pool TokenPoolContract) (TokenPoolView, error) {
+ owner, err := pool.Owner(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ typeAndVersion, err := pool.TypeAndVersion(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ token, err := pool.GetToken(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ allowList, err := pool.GetAllowList(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ allowListEnabled, err := pool.GetAllowListEnabled(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ remoteChains, err := pool.GetSupportedChains(nil)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ remoteChainConfigs := make(map[uint64]RemoteChainConfig)
+ for _, remoteChain := range remoteChains {
+ remotePools, err := pool.GetRemotePools(nil, remoteChain)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ remoteToken, err := pool.GetRemoteToken(nil, remoteChain)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ inboundState, err := GetCurrentInboundRateLimiterState(pool, remoteChain)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ outboundState, err := GetCurrentOutboundRateLimiterState(pool, remoteChain)
+ if err != nil {
+ return TokenPoolView{}, err
+ }
+ remoteChainConfigs[remoteChain] = RemoteChainConfig{
+ RemoteTokenAddress: remoteToken,
+ RemotePoolAddresses: remotePools,
+ InboundRateLimterConfig: token_pool.RateLimiterConfig{
+ IsEnabled: inboundState.IsEnabled,
+ Capacity: inboundState.Capacity,
+ Rate: inboundState.Rate,
+ },
+ OutboundRateLimiterConfig: token_pool.RateLimiterConfig{
+ IsEnabled: outboundState.IsEnabled,
+ Capacity: outboundState.Capacity,
+ Rate: outboundState.Rate,
+ },
+ }
+ }
+
+ return TokenPoolView{
+ ContractMetaData: types.ContractMetaData{
+ TypeAndVersion: typeAndVersion,
+ Address: pool.Address(),
+ Owner: owner,
+ },
+ Token: token,
+ RemoteChainConfigs: remoteChainConfigs,
+ AllowList: allowList,
+ AllowListEnabled: allowListEnabled,
+ }, nil
+}
+
+func GenerateLockReleaseTokenPoolView(pool *lock_release_token_pool.LockReleaseTokenPool) (LockReleaseTokenPoolView, error) {
+ basePoolView, err := GenerateTokenPoolView(pool)
+ if err != nil {
+ return LockReleaseTokenPoolView{}, err
+ }
+ acceptLiquidity, err := pool.CanAcceptLiquidity(nil)
+ if err != nil {
+ return LockReleaseTokenPoolView{}, err
+ }
+ rebalancer, err := pool.GetRebalancer(nil)
+ if err != nil {
+ return LockReleaseTokenPoolView{}, err
+ }
+ return LockReleaseTokenPoolView{
+ TokenPoolView: basePoolView,
+ AcceptLiquidity: acceptLiquidity,
+ Rebalancer: rebalancer,
+ }, nil
+}
+
+func GenerateUSDCTokenPoolView(pool *usdc_token_pool.USDCTokenPool) (USDCTokenPoolView, error) {
+ basePoolView, err := GenerateTokenPoolView(pool)
+ if err != nil {
+ return USDCTokenPoolView{}, err
+ }
+ tokenMessenger, err := pool.ITokenMessenger(nil)
+ if err != nil {
+ return USDCTokenPoolView{}, err
+ }
+ messageTransmitter, err := pool.IMessageTransmitter(nil)
+ if err != nil {
+ return USDCTokenPoolView{}, err
+ }
+ localDomain, err := pool.ILocalDomainIdentifier(nil)
+ if err != nil {
+ return USDCTokenPoolView{}, err
+ }
+ chainToDomain := make(map[uint64]usdc_token_pool.USDCTokenPoolDomain)
+ remoteChains := maps.Keys(basePoolView.RemoteChainConfigs)
+ for _, chainSel := range remoteChains {
+ domain, err := pool.GetDomain(nil, chainSel)
+ if err != nil {
+ return USDCTokenPoolView{}, err
+ }
+ chainToDomain[chainSel] = domain
+ }
+ return USDCTokenPoolView{
+ TokenPoolView: basePoolView,
+ TokenMessenger: tokenMessenger,
+ MessageTransmitter: messageTransmitter,
+ LocalDomain: localDomain,
+ ChainToDomain: chainToDomain,
+ }, nil
+}
diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go
index 8f698ba2277..7c35142ee5f 100644
--- a/deployment/ccip/view/view.go
+++ b/deployment/ccip/view/view.go
@@ -6,6 +6,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_0"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_2"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5_1"
"github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_6"
"github.com/smartcontractkit/chainlink/deployment/common/view"
common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0"
@@ -17,12 +18,15 @@ type ChainView struct {
// 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"`
- PriceRegistry map[string]v1_2.PriceRegistryView `json:"priceRegistry,omitempty"`
- EVM2EVMOnRamp map[string]v1_5.OnRampView `json:"evm2evmOnRamp,omitempty"`
- EVM2EVMOffRamp map[string]v1_5.OffRampView `json:"evm2evmOffRamp,omitempty"`
- RMN map[string]v1_5.RMNView `json:"rmn,omitempty"`
+ TokenAdminRegistry map[string]v1_5.TokenAdminRegistryView `json:"tokenAdminRegistry,omitempty"`
+ BurnMintTokenPool map[string]map[string]v1_5_1.TokenPoolView `json:"burnMintTokenPool,omitempty"`
+ LockReleaseTokenPool map[string]map[string]v1_5_1.LockReleaseTokenPoolView `json:"lockReleaseTokenPool,omitempty"`
+ USDCTokenPool map[string]map[string]v1_5_1.USDCTokenPoolView `json:"usdcTokenPool,omitempty"`
+ CommitStore map[string]v1_5.CommitStoreView `json:"commitStore,omitempty"`
+ PriceRegistry map[string]v1_2.PriceRegistryView `json:"priceRegistry,omitempty"`
+ EVM2EVMOnRamp map[string]v1_5.OnRampView `json:"evm2evmOnRamp,omitempty"`
+ EVM2EVMOffRamp map[string]v1_5.OffRampView `json:"evm2evmOffRamp,omitempty"`
+ RMN map[string]v1_5.RMNView `json:"rmn,omitempty"`
// v1.6
FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"`
diff --git a/deployment/changeset.go b/deployment/changeset.go
index abce4942203..fbde1dbb3d1 100644
--- a/deployment/changeset.go
+++ b/deployment/changeset.go
@@ -20,12 +20,22 @@ var (
// If the configuration is unexpected type or format, the changeset should return ErrInvalidConfig.
type ChangeSet[C any] func(e Environment, config C) (ChangesetOutput, error)
+// ProposedJob represents a job spec which has been proposed to a node, with the JobID returned by the
+// Job Distributor.
+type ProposedJob struct {
+ JobID string
+ Node string
+ Spec string
+}
+
// ChangesetOutput is the output of a Changeset function.
// Think of it like a state transition output.
// The address book here should contain only new addresses created in
// this changeset.
type ChangesetOutput struct {
- JobSpecs map[string][]string
+ // Deprecated: Prefer Jobs instead.
+ JobSpecs map[string][]string `deprecated:"true"`
+ Jobs []ProposedJob
Proposals []timelock.MCMSWithTimelockProposal
AddressBook AddressBook
}
diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go
index 648401289ff..86783ea4118 100644
--- a/deployment/common/changeset/deploy_link_token.go
+++ b/deployment/common/changeset/deploy_link_token.go
@@ -2,17 +2,19 @@ package changeset
import (
"context"
+ "fmt"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/gagliardetto/solana-go"
- solRpc "github.com/gagliardetto/solana-go/rpc"
chainsel "github.com/smartcontractkit/chain-selectors"
solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens"
+
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/common/types"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token"
)
@@ -24,7 +26,6 @@ const (
// DeployLinkToken deploys a link token contract to the chain identified by the ChainSelector.
func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) {
-
err := deployment.ValidateSelectorsInEnvironment(e, chains)
if err != nil {
return deployment.ChangesetOutput{}, err
@@ -57,6 +58,40 @@ func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.Chan
return deployment.ChangesetOutput{AddressBook: newAddresses}, nil
}
+// DeployStaticLinkToken deploys a static link token contract to the chain identified by the ChainSelector.
+func DeployStaticLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) {
+ err := deployment.ValidateSelectorsInEnvironment(e, chains)
+ if err != nil {
+ return deployment.ChangesetOutput{}, err
+ }
+ newAddresses := deployment.NewMemoryAddressBook()
+ for _, chainSel := range chains {
+ chain, ok := e.Chains[chainSel]
+ if !ok {
+ return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment: %d", chainSel)
+ }
+ _, err := deployment.DeployContract[*link_token_interface.LinkToken](e.Logger, chain, newAddresses,
+ func(chain deployment.Chain) deployment.ContractDeploy[*link_token_interface.LinkToken] {
+ linkTokenAddr, tx, linkToken, err2 := link_token_interface.DeployLinkToken(
+ chain.DeployerKey,
+ chain.Client,
+ )
+ return deployment.ContractDeploy[*link_token_interface.LinkToken]{
+ Address: linkTokenAddr,
+ Contract: linkToken,
+ Tx: tx,
+ Tv: deployment.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0),
+ Err: err2,
+ }
+ })
+ if err != nil {
+ e.Logger.Errorw("Failed to deploy static link token", "chain", chain.String(), "err", err)
+ return deployment.ChangesetOutput{}, err
+ }
+ }
+ return deployment.ChangesetOutput{AddressBook: newAddresses}, nil
+}
+
func deployLinkTokenContractEVM(
lggr logger.Logger,
chain deployment.Chain,
@@ -88,12 +123,17 @@ func deployLinkTokenContractSolana(
chain deployment.SolChain,
ab deployment.AddressBook,
) error {
- adminPublicKey := chain.DeployerKey.PublicKey()
+ tokenAdminPubKey := chain.DeployerKey.PublicKey()
mint, _ := solana.NewRandomPrivateKey()
- // this is the token address
- mintPublicKey := mint.PublicKey()
+ mintPublicKey := mint.PublicKey() // this is the token address
instructions, err := solTokenUtil.CreateToken(
- context.Background(), solana.Token2022ProgramID, mintPublicKey, adminPublicKey, TokenDecimalsSolana, chain.Client, solRpc.CommitmentConfirmed,
+ context.Background(),
+ solana.Token2022ProgramID,
+ mintPublicKey,
+ tokenAdminPubKey,
+ TokenDecimalsSolana,
+ chain.Client,
+ deployment.SolDefaultCommitment,
)
if err != nil {
lggr.Errorw("Failed to generate instructions for link token deployment", "chain", chain.String(), "err", err)
@@ -105,12 +145,11 @@ func deployLinkTokenContractSolana(
return err
}
tv := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0)
- lggr.Infow("Deployed contract", "Contract", tv.String(), "addr", mintPublicKey.String(), "chain", chain.String())
- err = ab.Save(chain.Selector, mintPublicKey.String(), tv)
+ lggr.Infow("Deployed contract", "Contract", tv.String(), "addr", mint.PublicKey().String(), "chain", chain.String())
+ err = ab.Save(chain.Selector, mint.PublicKey().String(), tv)
if err != nil {
lggr.Errorw("Failed to save link token", "chain", chain.String(), "err", err)
return err
}
-
return nil
}
diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go
index ddaca52c2d5..1491481a0fe 100644
--- a/deployment/common/changeset/deploy_link_token_test.go
+++ b/deployment/common/changeset/deploy_link_token_test.go
@@ -3,41 +3,10 @@ package changeset_test
import (
"testing"
- "github.com/stretchr/testify/require"
- "go.uber.org/zap/zapcore"
-
- "github.com/smartcontractkit/chainlink/deployment/common/changeset"
- "github.com/smartcontractkit/chainlink/deployment/environment/memory"
- "github.com/smartcontractkit/chainlink/v2/core/logger"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
)
func TestDeployLinkToken(t *testing.T) {
t.Parallel()
- lggr := logger.TestLogger(t)
- e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
- Chains: 1,
- SolChains: 1,
- })
- chain1 := e.AllChainSelectors()[0]
- solChain1 := e.AllChainSelectorsSolana()[0]
- e, err := changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{
- {
- Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken),
- Config: []uint64{chain1, solChain1},
- },
- })
- require.NoError(t, err)
- addrs, err := e.ExistingAddresses.AddressesForChain(chain1)
- require.NoError(t, err)
- state, err := changeset.MaybeLoadLinkTokenChainState(e.Chains[chain1], addrs)
- require.NoError(t, err)
- // View itself already unit tested
- _, err = state.GenerateLinkView()
- require.NoError(t, err)
-
- // solana test
- addrs, err = e.ExistingAddresses.AddressesForChain(solChain1)
- require.NoError(t, err)
- require.NotEmpty(t, addrs)
-
+ testhelpers.DeployLinkTokenTest(t, 0)
}
diff --git a/deployment/common/changeset/deploy_mcms_with_timelock.go b/deployment/common/changeset/deploy_mcms_with_timelock.go
index 06f9aba6164..10a48b0b22b 100644
--- a/deployment/common/changeset/deploy_mcms_with_timelock.go
+++ b/deployment/common/changeset/deploy_mcms_with_timelock.go
@@ -7,6 +7,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
+ "github.com/gagliardetto/solana-go"
+
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/common/changeset/internal"
"github.com/smartcontractkit/chainlink/deployment/common/types"
@@ -31,9 +33,14 @@ func ValidateOwnership(ctx context.Context, mcms bool, deployerKey, timelock com
return fmt.Errorf("failed to get owner: %w", err)
}
if mcms && owner != timelock {
- return fmt.Errorf("%s not owned by deployer key", contract.Address())
+ return fmt.Errorf("%s not owned by timelock", contract.Address())
} else if !mcms && owner != deployerKey {
return fmt.Errorf("%s not owned by deployer key", contract.Address())
}
return nil
}
+
+// TODO: SOLANA_CCIP
+func ValidateOwnershipSolana(ctx context.Context, mcms bool, deployerKey, timelock, ccipRouter solana.PublicKey) error {
+ return nil
+}
diff --git a/deployment/common/changeset/internal/mcms.go b/deployment/common/changeset/internal/mcms.go
index 61808e1cbbd..f40d73acc83 100644
--- a/deployment/common/changeset/internal/mcms.go
+++ b/deployment/common/changeset/internal/mcms.go
@@ -12,12 +12,23 @@ import (
"github.com/smartcontractkit/chainlink/deployment/common/view/v1_0"
)
+// DeployMCMSOption is a function that modifies a TypeAndVersion before or after deployment.
+type DeployMCMSOption func(*deployment.TypeAndVersion)
+
+// WithLabel is a functional option that sets a label on the TypeAndVersion.
+func WithLabel(label string) DeployMCMSOption {
+ return func(tv *deployment.TypeAndVersion) {
+ tv.AddLabel(label)
+ }
+}
+
func DeployMCMSWithConfig(
contractType deployment.ContractType,
lggr logger.Logger,
chain deployment.Chain,
ab deployment.AddressBook,
mcmConfig config.Config,
+ options ...DeployMCMSOption,
) (*deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig], error) {
groupQuorums, groupParents, signerAddresses, signerGroups := mcmConfig.ExtractSetConfigInputs()
mcm, err := deployment.DeployContract[*owner_helpers.ManyChainMultiSig](lggr, chain, ab,
@@ -26,8 +37,14 @@ func DeployMCMSWithConfig(
chain.DeployerKey,
chain.Client,
)
+
+ tv := deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0)
+ for _, option := range options {
+ option(&tv)
+ }
+
return deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig]{
- Address: mcmAddr, Contract: mcm, Tx: tx, Tv: deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), Err: err2,
+ Address: mcmAddr, Contract: mcm, Tx: tx, Tv: tv, Err: err2,
}
})
if err != nil {
@@ -84,15 +101,20 @@ func DeployMCMSWithTimelockContracts(
ab deployment.AddressBook,
config types.MCMSWithTimelockConfig,
) (*MCMSWithTimelockDeploy, error) {
- bypasser, err := DeployMCMSWithConfig(types.BypasserManyChainMultisig, lggr, chain, ab, config.Bypasser)
+ opts := []DeployMCMSOption{}
+ if config.Label != nil {
+ opts = append(opts, WithLabel(*config.Label))
+ }
+
+ bypasser, err := DeployMCMSWithConfig(types.BypasserManyChainMultisig, lggr, chain, ab, config.Bypasser, opts...)
if err != nil {
return nil, err
}
- canceller, err := DeployMCMSWithConfig(types.CancellerManyChainMultisig, lggr, chain, ab, config.Canceller)
+ canceller, err := DeployMCMSWithConfig(types.CancellerManyChainMultisig, lggr, chain, ab, config.Canceller, opts...)
if err != nil {
return nil, err
}
- proposer, err := DeployMCMSWithConfig(types.ProposerManyChainMultisig, lggr, chain, ab, config.Proposer)
+ proposer, err := DeployMCMSWithConfig(types.ProposerManyChainMultisig, lggr, chain, ab, config.Proposer, opts...)
if err != nil {
return nil, err
}
@@ -114,8 +136,14 @@ func DeployMCMSWithTimelockContracts(
[]common.Address{canceller.Address, proposer.Address, bypasser.Address}, // cancellers
[]common.Address{bypasser.Address}, // bypassers
)
+
+ tv := deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0)
+ if config.Label != nil {
+ tv.AddLabel(*config.Label)
+ }
+
return deployment.ContractDeploy[*owner_helpers.RBACTimelock]{
- Address: timelock, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0), Err: err2,
+ Address: timelock, Contract: cc, Tx: tx2, Tv: tv, Err: err2,
}
})
if err != nil {
@@ -130,8 +158,14 @@ func DeployMCMSWithTimelockContracts(
chain.Client,
timelock.Address,
)
+
+ tv := deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0)
+ if config.Label != nil {
+ tv.AddLabel(*config.Label)
+ }
+
return deployment.ContractDeploy[*owner_helpers.CallProxy]{
- Address: callProxy, Contract: cc, Tx: tx2, Tv: deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0), Err: err2,
+ Address: callProxy, Contract: cc, Tx: tx2, Tv: tv, Err: err2,
}
})
if err != nil {
diff --git a/deployment/common/changeset/internal/mcms_test.go b/deployment/common/changeset/internal/mcms_test.go
index 92822422daa..f404a645851 100644
--- a/deployment/common/changeset/internal/mcms_test.go
+++ b/deployment/common/changeset/internal/mcms_test.go
@@ -18,13 +18,36 @@ import (
func TestDeployMCMSWithConfig(t *testing.T) {
lggr := logger.TestLogger(t)
+
chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{
chainsel.TEST_90000001.EvmChainID,
}, 1)
ab := deployment.NewMemoryAddressBook()
- _, err := internal.DeployMCMSWithConfig(types.ProposerManyChainMultisig,
- lggr, chains[chainsel.TEST_90000001.Selector], ab, proposalutils.SingleGroupMCMS(t))
+
+ // 1) Test WITHOUT a label
+ mcmNoLabel, err := internal.DeployMCMSWithConfig(
+ types.ProposerManyChainMultisig,
+ lggr,
+ chains[chainsel.TEST_90000001.Selector],
+ ab,
+ proposalutils.SingleGroupMCMS(t),
+ )
+ require.NoError(t, err)
+ require.Empty(t, mcmNoLabel.Tv.Labels, "expected no label to be set")
+
+ // 2) Test WITH a label
+ label := "SA"
+ mcmWithLabel, err := internal.DeployMCMSWithConfig(
+ types.ProposerManyChainMultisig,
+ lggr,
+ chains[chainsel.TEST_90000001.Selector],
+ ab,
+ proposalutils.SingleGroupMCMS(t),
+ internal.WithLabel(label),
+ )
require.NoError(t, err)
+ require.NotNil(t, mcmWithLabel.Tv.Labels, "expected labels to be set")
+ require.Contains(t, mcmWithLabel.Tv.Labels, label, "label mismatch")
}
func TestDeployMCMSWithTimelockContracts(t *testing.T) {
diff --git a/deployment/common/changeset/save_existing.go b/deployment/common/changeset/save_existing.go
index 17fdc0a8025..602d41dc84e 100644
--- a/deployment/common/changeset/save_existing.go
+++ b/deployment/common/changeset/save_existing.go
@@ -8,6 +8,9 @@ import (
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
"github.com/smartcontractkit/chainlink/deployment"
+
+ "github.com/mr-tron/base58"
+ chain_selectors "github.com/smartcontractkit/chain-selectors"
)
var (
@@ -15,7 +18,7 @@ var (
)
type Contract struct {
- Address common.Address
+ Address string
TypeAndVersion deployment.TypeAndVersion
ChainSelector uint64
}
@@ -29,9 +32,30 @@ func (cfg ExistingContractsConfig) Validate() error {
if err := deployment.IsValidChainSelector(ec.ChainSelector); err != nil {
return fmt.Errorf("invalid chain selector: %d - %w", ec.ChainSelector, err)
}
- if ec.Address == (common.Address{}) {
+ if ec.Address == "" {
return errors.New("address must be set")
}
+ family, err := chain_selectors.GetSelectorFamily(ec.ChainSelector)
+ if err != nil {
+ return err
+ }
+ switch family {
+ case chain_selectors.FamilySolana:
+ decoded, err := base58.Decode(ec.Address)
+ if err != nil {
+ return fmt.Errorf("address must be a valid Solana address (i.e. base58 encoded): %w", err)
+ }
+ if len(decoded) != 32 {
+ return fmt.Errorf("address must be a valid Solana address, got %d bytes expected 32", len(decoded))
+ }
+ case chain_selectors.FamilyEVM:
+ a := common.HexToAddress(ec.Address)
+ if a == (common.Address{}) {
+ return fmt.Errorf("invalid address: %s", ec.Address)
+ }
+ default:
+ return fmt.Errorf("unsupported chain family: %s", family)
+ }
if ec.TypeAndVersion.Type == "" {
return errors.New("type must be set")
}
@@ -51,7 +75,7 @@ func SaveExistingContractsChangeset(env deployment.Environment, cfg ExistingCont
}
ab := deployment.NewMemoryAddressBook()
for _, ec := range cfg.ExistingContracts {
- err = ab.Save(ec.ChainSelector, ec.Address.String(), ec.TypeAndVersion)
+ err = ab.Save(ec.ChainSelector, ec.Address, ec.TypeAndVersion)
if err != nil {
env.Logger.Errorw("Failed to save existing contract", "err", err, "addressBook", ab)
return deployment.ChangesetOutput{}, fmt.Errorf("failed to save existing contract: %w", err)
@@ -61,5 +85,6 @@ func SaveExistingContractsChangeset(env deployment.Environment, cfg ExistingCont
Proposals: []timelock.MCMSWithTimelockProposal{},
AddressBook: ab,
JobSpecs: nil,
+ Jobs: nil,
}, nil
}
diff --git a/deployment/common/changeset/save_existing_test.go b/deployment/common/changeset/save_existing_test.go
index a7e8c9068f3..dc001e030c8 100644
--- a/deployment/common/changeset/save_existing_test.go
+++ b/deployment/common/changeset/save_existing_test.go
@@ -25,7 +25,7 @@ func TestSaveExisting(t *testing.T) {
ExistingContracts := ExistingContractsConfig{
ExistingContracts: []Contract{
{
- Address: common.BigToAddress(big.NewInt(1)),
+ Address: common.BigToAddress(big.NewInt(1)).String(),
TypeAndVersion: deployment.TypeAndVersion{
Type: "dummy1",
Version: deployment.Version1_5_0,
@@ -33,7 +33,7 @@ func TestSaveExisting(t *testing.T) {
ChainSelector: chainsel.TEST_90000001.Selector,
},
{
- Address: common.BigToAddress(big.NewInt(2)),
+ Address: common.BigToAddress(big.NewInt(2)).String(),
TypeAndVersion: deployment.TypeAndVersion{
Type: "dummy2",
Version: deployment.Version1_1_0,
diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go
index 0db34abad71..f57686d1d03 100644
--- a/deployment/common/changeset/state.go
+++ b/deployment/common/changeset/state.go
@@ -95,42 +95,42 @@ func MaybeLoadMCMSWithTimelockChainState(chain deployment.Chain, addresses map[s
canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0)
bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0)
+ // Convert map keys to a slice
+ wantTypes := []deployment.TypeAndVersion{timelock, proposer, canceller, bypasser, callProxy}
+
// Ensure we either have the bundle or not.
- _, err := deployment.AddressesContainBundle(addresses,
- map[deployment.TypeAndVersion]struct{}{
- timelock: {}, proposer: {}, canceller: {}, bypasser: {}, callProxy: {},
- })
+ _, err := deployment.AddressesContainBundle(addresses, wantTypes)
if err != nil {
return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err)
}
for address, tvStr := range addresses {
- switch tvStr {
- case timelock:
+ switch {
+ case tvStr.Type == timelock.Type && tvStr.Version.String() == timelock.Version.String():
tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.Timelock = tl
- case callProxy:
+ case tvStr.Type == callProxy.Type && tvStr.Version.String() == callProxy.Version.String():
cp, err := owner_helpers.NewCallProxy(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.CallProxy = cp
- case proposer:
+ case tvStr.Type == proposer.Type && tvStr.Version.String() == proposer.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.ProposerMcm = mcms
- case bypasser:
+ case tvStr.Type == bypasser.Type && tvStr.Version.String() == bypasser.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.BypasserMcm = mcms
- case canceller:
+ case tvStr.Type == canceller.Type && tvStr.Version.String() == canceller.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
@@ -176,14 +176,18 @@ func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64
func MaybeLoadLinkTokenChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) {
state := LinkTokenState{}
linkToken := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0)
- // Perhaps revisit if we have a use case for multiple.
- _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{linkToken: {}})
+
+ // Convert map keys to a slice
+ wantTypes := []deployment.TypeAndVersion{linkToken}
+
+ // Ensure we either have the bundle or not.
+ _, err := deployment.AddressesContainBundle(addresses, wantTypes)
if err != nil {
return nil, fmt.Errorf("unable to check link token on chain %s error: %w", chain.Name(), err)
}
+
for address, tvStr := range addresses {
- switch tvStr {
- case linkToken:
+ if tvStr.Type == linkToken.Type && tvStr.Version.String() == linkToken.Version.String() {
lt, err := link_token.NewLinkToken(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
@@ -208,14 +212,18 @@ func (s StaticLinkTokenState) GenerateStaticLinkView() (v1_0.StaticLinkTokenView
func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*StaticLinkTokenState, error) {
state := StaticLinkTokenState{}
staticLinkToken := deployment.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0)
- // Perhaps revisit if we have a use case for multiple.
- _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{staticLinkToken: {}})
+
+ // Convert map keys to a slice
+ wantTypes := []deployment.TypeAndVersion{staticLinkToken}
+
+ // Ensure we either have the bundle or not.
+ _, err := deployment.AddressesContainBundle(addresses, wantTypes)
if err != nil {
return nil, fmt.Errorf("unable to check static link token on chain %s error: %w", chain.Name(), err)
}
+
for address, tvStr := range addresses {
- switch tvStr {
- case staticLinkToken:
+ if tvStr.Type == staticLinkToken.Type && tvStr.Version.String() == staticLinkToken.Version.String() {
lt, err := link_token_interface.NewLinkToken(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go
index a8105b26561..3c2409566eb 100644
--- a/deployment/common/changeset/test_helpers.go
+++ b/deployment/common/changeset/test_helpers.go
@@ -52,6 +52,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe
addresses = currentEnv.ExistingAddresses
}
if out.JobSpecs != nil {
+ // TODO: Delete this when out.JobSpecs are no longer in use.
ctx := testcontext.Get(t)
for nodeID, jobs := range out.JobSpecs {
for _, job := range jobs {
@@ -67,6 +68,9 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe
}
}
}
+ if out.Jobs != nil {
+ // do nothing, as these jobs auto-accept.
+ }
if out.Proposals != nil {
for _, prop := range out.Proposals {
chains := mapset.NewSet[uint64]()
diff --git a/deployment/common/proposalutils/mcms_helpers.go b/deployment/common/proposalutils/mcms_helpers.go
index 8b7153e526b..be437479d5e 100644
--- a/deployment/common/proposalutils/mcms_helpers.go
+++ b/deployment/common/proposalutils/mcms_helpers.go
@@ -229,42 +229,40 @@ func MaybeLoadMCMSWithTimelockContracts(chain deployment.Chain, addresses map[st
canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0)
bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0)
- // Ensure we either have the bundle or not.
- _, err := deployment.AddressesContainBundle(addresses,
- map[deployment.TypeAndVersion]struct{}{
- timelock: {}, proposer: {}, canceller: {}, bypasser: {}, callProxy: {},
- })
+ // Convert map keys to a slice
+ wantTypes := []deployment.TypeAndVersion{timelock, proposer, canceller, bypasser, callProxy}
+ _, err := deployment.AddressesContainBundle(addresses, wantTypes)
if err != nil {
return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err)
}
for address, tvStr := range addresses {
- switch tvStr {
- case timelock:
+ switch {
+ case tvStr.Type == timelock.Type && tvStr.Version.String() == timelock.Version.String():
tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.Timelock = tl
- case callProxy:
+ case tvStr.Type == callProxy.Type && tvStr.Version.String() == callProxy.Version.String():
cp, err := owner_helpers.NewCallProxy(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.CallProxy = cp
- case proposer:
+ case tvStr.Type == proposer.Type && tvStr.Version.String() == proposer.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.ProposerMcm = mcms
- case bypasser:
+ case tvStr.Type == bypasser.Type && tvStr.Version.String() == bypasser.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
}
state.BypasserMcm = mcms
- case canceller:
+ case tvStr.Type == canceller.Type && tvStr.Version.String() == canceller.Version.String():
mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client)
if err != nil {
return nil, err
diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go
index c86fb3e9887..d78ddb0d414 100644
--- a/deployment/common/types/types.go
+++ b/deployment/common/types/types.go
@@ -33,6 +33,7 @@ type MCMSWithTimelockConfig struct {
Bypasser config.Config
Proposer config.Config
TimelockMinDelay *big.Int
+ Label *string
}
type OCRParameters struct {
diff --git a/deployment/environment/crib/ccip_deployer.go b/deployment/environment/crib/ccip_deployer.go
index 96ff9071890..5c4913b799e 100644
--- a/deployment/environment/crib/ccip_deployer.go
+++ b/deployment/environment/crib/ccip_deployer.go
@@ -278,7 +278,7 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de
Config: changeset.UpdateFeeQuoterDestsConfig{
UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{
src: {
- dst: changeset.DefaultFeeQuoterDestChainConfig(),
+ dst: changeset.DefaultFeeQuoterDestChainConfig(true),
},
},
},
diff --git a/deployment/environment/devenv/don.go b/deployment/environment/devenv/don.go
index a8912254d1d..ea0a43924e3 100644
--- a/deployment/environment/devenv/don.go
+++ b/deployment/environment/devenv/don.go
@@ -24,6 +24,7 @@ import (
const (
NodeLabelKeyType = "type"
+ NodeLabelP2PIDType = "p2p_id"
NodeLabelValueBootstrap = "bootstrap"
NodeLabelValuePlugin = "plugin"
)
@@ -68,7 +69,7 @@ func (don *DON) ReplayAllLogs(blockbyChain map[uint64]uint64) error {
func (don *DON) NodeIds() []string {
var nodeIds []string
for _, node := range don.Nodes {
- nodeIds = append(nodeIds, node.NodeId)
+ nodeIds = append(nodeIds, node.NodeID)
}
return nodeIds
}
@@ -130,6 +131,15 @@ func NewRegisteredDON(ctx context.Context, nodeInfo []NodeInfo, jd JobDistributo
// multi address is not applicable for non-bootstrap nodes
// explicitly set it to empty string to denote that
node.multiAddr = ""
+
+ // set admin address for non-bootstrap nodes
+ node.adminAddr = info.AdminAddr
+
+ // capability registry requires non-null admin address; use arbitrary default value if node is not configured
+ if info.AdminAddr == "" {
+ node.adminAddr = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
+ }
+
node.labels = append(node.labels, &ptypes.Label{
Key: NodeLabelKeyType,
Value: ptr(NodeLabelValuePlugin),
@@ -167,15 +177,16 @@ func NewNode(nodeInfo NodeInfo) (*Node, error) {
}
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 id to node's account address mapping for supported chains
- gqlClient client.Client // graphql client to interact with the node
- restClient *clclient.ChainlinkClient // rest client to interact with the node
- labels []*ptypes.Label // labels with which the node is registered with the job distributor
- 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
+ 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 id to node's account address mapping for supported chains
+ Ocr2KeyBundleID string // OCR2 key bundle id of the node
+ 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 {
@@ -183,6 +194,10 @@ type JDChainConfigInput struct {
ChainType string
}
+func (n *Node) Labels() []*ptypes.Label {
+ return n.labels
+}
+
// 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".
@@ -234,6 +249,7 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []JDChai
if ocr2BundleId == "" {
return fmt.Errorf("no OCR2 key bundle id found for node %s", n.Name)
}
+ n.Ocr2KeyBundleID = ocr2BundleId
// fetch node labels to know if the node is bootstrap or plugin
isBootstrap := false
for _, label := range n.labels {
@@ -248,7 +264,7 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []JDChai
// check the node chain config to see if this chain already exists
nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{
Filter: &nodev1.ListNodeChainConfigsRequest_Filter{
- NodeIds: []string{n.NodeId},
+ NodeIds: []string{n.NodeID},
}})
if err != nil {
return retry.RetryableError(fmt.Errorf("failed to list node chain configs for node %s, retrying..: %w", n.Name, err))
@@ -344,7 +360,7 @@ func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistribut
return fmt.Errorf("no peer id found for node %s", n.Name)
}
n.labels = append(n.labels, &ptypes.Label{
- Key: "p2p_id",
+ Key: NodeLabelP2PIDType,
Value: peerID,
})
@@ -361,7 +377,7 @@ func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistribut
Filter: &nodev1.ListNodesRequest_Filter{
Selectors: []*ptypes.Selector{
{
- Key: "p2p_id",
+ Key: NodeLabelP2PIDType,
Op: ptypes.SelectorOp_EQ,
Value: peerID,
},
@@ -375,7 +391,7 @@ func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistribut
if len(nodes) == 0 {
return fmt.Errorf("failed to find node: %v", n.Name)
}
- n.NodeId = nodes[0].Id
+ n.NodeID = nodes[0].Id
return nil
} else if err != nil {
return fmt.Errorf("failed to register node %s: %w", n.Name, err)
@@ -383,7 +399,7 @@ func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistribut
if registerResponse.GetNode().GetId() == "" {
return fmt.Errorf("no node id returned from job distributor for node %s", n.Name)
}
- n.NodeId = registerResponse.GetNode().GetId()
+ n.NodeID = registerResponse.GetNode().GetId()
return nil
}
@@ -431,13 +447,13 @@ func (n *Node) SetUpAndLinkJobDistributor(ctx context.Context, jd JobDistributor
// 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,
+ Id: n.NodeID,
})
if err != nil {
return retry.RetryableError(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)
+ 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))
diff --git a/deployment/environment/devenv/jd.go b/deployment/environment/devenv/jd.go
index 755f5cc70cd..e3feb35f7dd 100644
--- a/deployment/environment/devenv/jd.go
+++ b/deployment/environment/devenv/jd.go
@@ -166,7 +166,7 @@ func (jd JobDistributor) ProposeJob(ctx context.Context, in *jobv1.ProposeJobReq
return res, nil
}
for _, node := range jd.don.Nodes {
- if node.NodeId != in.NodeId {
+ if node.NodeID != in.NodeId {
continue
}
// TODO : is there a way to accept the job with proposal id?
diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go
index 59b7679b9bd..d14be7ba4e7 100644
--- a/deployment/environment/memory/chain.go
+++ b/deployment/environment/memory/chain.go
@@ -20,7 +20,6 @@ import (
"github.com/gagliardetto/solana-go"
solRpc "github.com/gagliardetto/solana-go/rpc"
"github.com/hashicorp/consul/sdk/freeport"
- "github.com/mr-tron/base58"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
@@ -98,10 +97,7 @@ func generateSolanaKeypair(t testing.TB) (solana.PrivateKey, string, error) {
}
// Convert private key bytes to JSON array
- privateKeyBytes, err := base58.Decode(privateKey.String())
- if err != nil {
- return solana.PrivateKey{}, "", fmt.Errorf("failed to decode private key: %w", err)
- }
+ privateKeyBytes := []byte(privateKey)
// Convert bytes to array of integers for JSON
intArray := make([]int, len(privateKeyBytes))
@@ -194,24 +190,41 @@ func solChain(t *testing.T, chainID uint64, adminKey *solana.PrivateKey) (string
err := framework.DefaultNetwork(once)
require.NoError(t, err)
- port := freeport.GetOne(t)
-
- bcInput := &blockchain.Input{
- Type: "solana",
- ChainID: strconv.FormatUint(chainID, 10),
- PublicKey: adminKey.PublicKey().String(),
- Port: strconv.Itoa(port),
- ContractsDir: ProgramsPath,
- SolanaPrograms: map[string]string{
- "ccip_router": solTestConfig.CcipRouterProgram.String(),
- },
+ maxRetries := 10
+ var url, wsURL string
+ for i := 0; i < maxRetries; i++ {
+ port := freeport.GetOne(t)
+
+ programIds := map[string]string{
+ "ccip_router": solTestConfig.CcipRouterProgram.String(),
+ "token_pool": solTestConfig.CcipTokenPoolProgram.String(),
+ "ccip_receiver": solTestConfig.CcipLogicReceiver.String(),
+ }
+
+ bcInput := &blockchain.Input{
+ Type: "solana",
+ ChainID: strconv.FormatUint(chainID, 10),
+ PublicKey: adminKey.PublicKey().String(),
+ Port: strconv.Itoa(port),
+ ContractsDir: ProgramsPath,
+ // TODO: this should be solTestConfig.CCIPRouterProgram
+ // TODO: make this a function
+ SolanaPrograms: programIds,
+ }
+ output, err := blockchain.NewBlockchainNetwork(bcInput)
+ if err != nil {
+ t.Logf("Error creating solana network: %v", err)
+ time.Sleep(time.Second)
+ maxRetries -= 1
+ continue
+ }
+ require.NoError(t, err)
+ testcontainers.CleanupContainer(t, output.Container)
+ url = output.Nodes[0].HostHTTPUrl
+ wsURL = output.Nodes[0].HostWSUrl
+ break
}
- output, err := blockchain.NewBlockchainNetwork(bcInput)
require.NoError(t, err)
- testcontainers.CleanupContainer(t, output.Container)
-
- url := output.Nodes[0].HostHTTPUrl
- wsURL := output.Nodes[0].HostWSUrl
// Wait for api server to boot
client := solRpc.New(url)
@@ -231,6 +244,7 @@ func solChain(t *testing.T, chainID uint64, adminKey *solana.PrivateKey) (string
}
require.True(t, ready)
t.Logf("solana-test-validator is ready at %s", url)
+ time.Sleep(15 * time.Second) // we have slot errors that force retries if the chain is not given enough time to boot
return url, wsURL, nil
}
diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go
index a739a1d0c7d..48fa7d71d46 100644
--- a/deployment/environment/memory/environment.go
+++ b/deployment/environment/memory/environment.go
@@ -24,7 +24,7 @@ import (
solRpc "github.com/gagliardetto/solana-go/rpc"
- solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
+ solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
)
@@ -82,7 +82,7 @@ func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]depl
func NewMemoryChainsSol(t *testing.T, numChains int) map[uint64]deployment.SolChain {
mchains := GenerateChainsSol(t, numChains)
- return generateMemoryChainSol(t, mchains)
+ return generateMemoryChainSol(mchains)
}
func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) {
@@ -137,7 +137,7 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de
return chains
}
-func generateMemoryChainSol(t *testing.T, inputs map[uint64]SolanaChain) map[uint64]deployment.SolChain {
+func generateMemoryChainSol(inputs map[uint64]SolanaChain) map[uint64]deployment.SolChain {
chains := make(map[uint64]deployment.SolChain)
for cid, chain := range inputs {
chain := chain
@@ -149,21 +149,18 @@ func generateMemoryChainSol(t *testing.T, inputs map[uint64]SolanaChain) map[uin
WSURL: chain.WSURL,
KeypairPath: chain.KeypairPath,
ProgramsPath: ProgramsPath,
- Confirm: func(instructions []solana.Instruction, opts ...solCommomUtil.TxModifier) error {
- _, err := solCommomUtil.SendAndConfirm(
+ Confirm: func(instructions []solana.Instruction, opts ...solCommonUtil.TxModifier) error {
+ _, err := solCommonUtil.SendAndConfirm(
context.Background(), chain.Client, instructions, chain.DeployerKey, solRpc.CommitmentConfirmed, opts...,
)
- if err != nil {
- return err
- }
- return nil
+ return err
},
}
}
return chains
}
-func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node {
+func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, solChains map[uint64]deployment.SolChain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node {
nodesByPeerID := make(map[string]Node)
if numNodes+numBootstraps == 0 {
return nodesByPeerID
@@ -173,13 +170,13 @@ func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment
// since we won't run a bootstrapper and a plugin oracle on the same
// chainlink node in production.
for i := 0; i < numBootstraps; i++ {
- node := NewNode(t, ports[i], chains, nil, logLevel, true /* bootstrap */, registryConfig)
+ node := NewNode(t, ports[i], chains, solChains, logLevel, true /* bootstrap */, registryConfig)
nodesByPeerID[node.Keys.PeerID.String()] = *node
// Note in real env, this ID is allocated by JD.
}
for i := 0; i < numNodes; i++ {
// grab port offset by numBootstraps, since above loop also takes some ports.
- node := NewNode(t, ports[numBootstraps+i], chains, nil, logLevel, false /* bootstrap */, registryConfig)
+ node := NewNode(t, ports[numBootstraps+i], chains, solChains, logLevel, false /* bootstrap */, registryConfig)
nodesByPeerID[node.Keys.PeerID.String()] = *node
// Note in real env, this ID is allocated by JD.
}
@@ -190,6 +187,7 @@ func NewMemoryEnvironmentFromChainsNodes(
ctx func() context.Context,
lggr logger.Logger,
chains map[uint64]deployment.Chain,
+ solChains map[uint64]deployment.SolChain,
nodes map[string]Node,
) deployment.Environment {
var nodeIDs []string
@@ -201,7 +199,7 @@ func NewMemoryEnvironmentFromChainsNodes(
lggr,
deployment.NewMemoryAddressBook(),
chains,
- nil,
+ solChains,
nodeIDs, // Note these have the p2p_ prefix.
NewMemoryJobClient(nodes),
ctx,
@@ -213,7 +211,7 @@ func NewMemoryEnvironmentFromChainsNodes(
func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment {
chains, _ := NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain)
solChains := NewMemoryChainsSol(t, config.SolChains)
- nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig)
+ nodes := NewNodes(t, logLevel, chains, solChains, config.Nodes, config.Bootstraps, config.RegistryConfig)
var nodeIDs []string
for id := range nodes {
nodeIDs = append(nodeIDs, id)
diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go
index 97e60c646b9..0100c26f6dc 100644
--- a/deployment/environment/memory/node.go
+++ b/deployment/environment/memory/node.go
@@ -169,7 +169,7 @@ func NewNode(
mailMon := mailbox.NewMonitor("node", lggr.Named("mailbox"))
evmOpts := chainlink.EVMFactoryConfig{
ChainOpts: legacyevm.ChainOpts{
- AppConfig: cfg,
+ ChainConfigs: cfg.EVMConfigs(),
DatabaseConfig: cfg.Database(),
ListenerConfig: cfg.Database().Listener(),
FeatureConfig: cfg.Feature(),
diff --git a/deployment/go.mod b/deployment/go.mod
index f7fdec3e7b2..b9cd7a79ff0 100644
--- a/deployment/go.mod
+++ b/deployment/go.mod
@@ -9,7 +9,7 @@ replace github.com/smartcontractkit/chainlink/v2 => ../
// Using a separate inline `require` here to avoid surrounding line changes
// creating potential merge conflicts.
-require github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0
+require github.com/smartcontractkit/chainlink/v2 v2.0.0-20250128231431-9279badae2f0
require (
github.com/Khan/genqlient v0.7.0
@@ -30,10 +30,10 @@ require (
github.com/rs/zerolog v1.33.0
github.com/sethvargo/go-retry v0.2.4
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix
- github.com/smartcontractkit/chain-selectors v1.0.36
- github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847
+ github.com/smartcontractkit/chain-selectors v1.0.37
+ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b
- github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36
+ github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0
github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250121222331-a7010b4b8ce5
@@ -48,7 +48,7 @@ require (
golang.org/x/oauth2 v0.23.0
golang.org/x/sync v0.10.0
google.golang.org/grpc v1.67.1
- google.golang.org/protobuf v1.35.1
+ google.golang.org/protobuf v1.36.4
gopkg.in/guregu/null.v4 v4.0.0
)
@@ -417,10 +417,10 @@ require (
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 // indirect
- github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc // indirect
+ github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 // indirect
github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect
- github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 // indirect
+ github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a // indirect
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect
github.com/smartcontractkit/chainlink-protos/svr v0.0.0-20250123084029-58cce9b32112 // indirect
github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20250117224137-afdcdd75070d // indirect
diff --git a/deployment/go.sum b/deployment/go.sum
index 102312de24a..425cbdb1410 100644
--- a/deployment/go.sum
+++ b/deployment/go.sum
@@ -1390,24 +1390,24 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY=
-github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0=
-github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 h1:kCcrM/osIQFmHx7ZOxeGIeYAMkSmTxkOXcmqHNlXQXQ=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 h1:+/KEPuWctPObgOoEEBCnli1/H3XnjMdCY3Tn+J32XRM=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b h1:eNsqumP7VVJudA7gEcTKVFofealwbPJRinUw24uEmII=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 h1:w7w42ml8MOxdoyAZ9+og0342UkiH3deRM1V0Pj5JR5g=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4/go.mod h1:wtdAmAUMooLavbrTA7PgHg40lyDlKesxI/RR+5Xcz18=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36 h1:bS51NFGHVjkCy7yu9L2Ss4sBsCW6jpa5GuhRAdWWxzM=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc h1:WZERXv2hTYRA0NpWg79ci/ZZSxucmvkty39iUOV8d7I=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc/go.mod h1:2iGmU7fkVsy21Sw8D+OhtYekHLUlJKHzwePKcxIx3Ac=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 h1:CvDfgWoLoYPapOumE/UZCplfCu5oNmy9BuH+6V6+fJ8=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c=
github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a h1:fVtn9CDfoGF40FeqGwLvp9belfIw7VT3lgQTctFGP5E=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM=
@@ -2180,8 +2180,8 @@ 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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
-google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/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=
diff --git a/deployment/keystone/changeset/append_node_capabilities.go b/deployment/keystone/changeset/append_node_capabilities.go
index 9ae1923d270..826ba4601f7 100644
--- a/deployment/keystone/changeset/append_node_capabilities.go
+++ b/deployment/keystone/changeset/append_node_capabilities.go
@@ -21,7 +21,7 @@ type AppendNodeCapabilitiesRequest = MutateNodeCapabilitiesRequest
// AppendNodeCapabilities adds any new capabilities to the registry, merges the new capabilities with the existing capabilities
// of the node, and updates the nodes in the registry host the union of the new and existing capabilities.
func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilitiesRequest) (deployment.ChangesetOutput, error) {
- c, err := req.convert(env)
+ c, contractSet, err := req.convert(env)
if err != nil {
return deployment.ChangesetOutput{}, err
}
@@ -35,10 +35,10 @@ func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilit
return out, errors.New("expected MCMS operation to be non-nil")
}
timelocksPerChain := map[uint64]common.Address{
- c.Chain.Selector: c.ContractSet.Timelock.Address(),
+ c.Chain.Selector: contractSet.Timelock.Address(),
}
proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{
- c.Chain.Selector: c.ContractSet.ProposerMcm,
+ c.Chain.Selector: contractSet.ProposerMcm,
}
proposal, err := proposalutils.BuildProposalFromBatches(
@@ -56,27 +56,24 @@ func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilit
return out, nil
}
-func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment) (*internal.AppendNodeCapabilitiesRequest, error) {
- if err := req.Validate(); err != nil {
- return nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err)
- }
- registryChain, ok := e.Chains[req.RegistryChainSel]
- if !ok {
- return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel)
+func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment) (*internal.AppendNodeCapabilitiesRequest, *ContractSet, error) {
+ if err := req.Validate(e); err != nil {
+ return nil, nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err)
}
+ registryChain := e.Chains[req.RegistryChainSel] // exists because of the validation above
resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{
Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain},
AddressBook: e.ExistingAddresses,
})
if err != nil {
- return nil, fmt.Errorf("failed to get contract sets: %w", err)
+ return nil, nil, fmt.Errorf("failed to get contract sets: %w", err)
}
- contracts := resp.ContractSets[req.RegistryChainSel]
+ contractSet := resp.ContractSets[req.RegistryChainSel]
return &internal.AppendNodeCapabilitiesRequest{
- Chain: registryChain,
- ContractSet: &contracts,
- P2pToCapabilities: req.P2pToCapabilities,
- UseMCMS: req.UseMCMS(),
- }, nil
+ Chain: registryChain,
+ CapabilitiesRegistry: contractSet.CapabilitiesRegistry,
+ P2pToCapabilities: req.P2pToCapabilities,
+ UseMCMS: req.UseMCMS(),
+ }, &contractSet, nil
}
diff --git a/deployment/keystone/changeset/compatiblity.go b/deployment/keystone/changeset/compatiblity.go
index 67b799a02ce..a353e1acc92 100644
--- a/deployment/keystone/changeset/compatiblity.go
+++ b/deployment/keystone/changeset/compatiblity.go
@@ -79,6 +79,9 @@ var RegisterDons = internal.RegisterDons
// DONToRegister is the minimal information needed to register a DON with the capabilities registry
type DONToRegister = internal.DONToRegister
+// NOP is a node operator profile, required to register a node with the capabilities registry
+type NOP = internal.NOP
+
// ConfigureContractsRequest is a request to configure ALL the contracts
type ConfigureContractsRequest = internal.ConfigureContractsRequest
diff --git a/deployment/keystone/changeset/internal/append_node_capabilities.go b/deployment/keystone/changeset/internal/append_node_capabilities.go
index a87688b5427..85203120063 100644
--- a/deployment/keystone/changeset/internal/append_node_capabilities.go
+++ b/deployment/keystone/changeset/internal/append_node_capabilities.go
@@ -12,8 +12,8 @@ import (
)
type AppendNodeCapabilitiesRequest struct {
- Chain deployment.Chain
- ContractSet *ContractSet
+ Chain deployment.Chain
+ CapabilitiesRegistry *kcr.CapabilitiesRegistry
P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability
UseMCMS bool
@@ -23,7 +23,7 @@ func (req *AppendNodeCapabilitiesRequest) Validate() error {
if len(req.P2pToCapabilities) == 0 {
return errors.New("p2pToCapabilities is empty")
}
- if req.ContractSet.CapabilitiesRegistry == nil {
+ if req.CapabilitiesRegistry == nil {
return errors.New("registry is nil")
}
return nil
@@ -37,7 +37,7 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR
// for each node, merge the new capabilities with the existing ones and update the node
updatesByPeer := make(map[p2pkey.PeerID]NodeUpdate)
for p2pID, caps := range req.P2pToCapabilities {
- caps, err := AppendCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, []p2pkey.PeerID{p2pID}, caps)
+ caps, err := AppendCapabilities(lggr, req.CapabilitiesRegistry, req.Chain, []p2pkey.PeerID{p2pID}, caps)
if err != nil {
return nil, fmt.Errorf("failed to append capabilities for p2p %s: %w", p2pID, err)
}
@@ -49,17 +49,17 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR
for _, cap := range req.P2pToCapabilities {
capabilities = append(capabilities, cap...)
}
- op, err := AddCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS)
+ op, err := AddCapabilities(lggr, req.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS)
if err != nil {
return nil, fmt.Errorf("failed to add capabilities: %w", err)
}
updateNodesReq := &UpdateNodesRequest{
- Chain: req.Chain,
- ContractSet: req.ContractSet,
- P2pToUpdates: updatesByPeer,
- UseMCMS: req.UseMCMS,
- Ops: op,
+ Chain: req.Chain,
+ CapabilitiesRegistry: req.CapabilitiesRegistry,
+ P2pToUpdates: updatesByPeer,
+ UseMCMS: req.UseMCMS,
+ Ops: op,
}
resp, err := UpdateNodes(lggr, updateNodesReq)
if err != nil {
diff --git a/deployment/keystone/changeset/internal/append_node_capabilities_test.go b/deployment/keystone/changeset/internal/append_node_capabilities_test.go
index 6d26133195d..440c3917341 100644
--- a/deployment/keystone/changeset/internal/append_node_capabilities_test.go
+++ b/deployment/keystone/changeset/internal/append_node_capabilities_test.go
@@ -10,7 +10,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+ kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)
@@ -95,7 +95,7 @@ func TestAppendNodeCapabilities(t *testing.T) {
setupResp := kstest.SetupTestRegistry(t, lggr, tt.args.initialState)
tt.args.req.Chain = setupResp.Chain
- tt.args.req.ContractSet = setupResp.ContractSet
+ tt.args.req.CapabilitiesRegistry = setupResp.CapabilitiesRegistry
got, err := internal.AppendNodeCapabilitiesImpl(tt.args.lggr, tt.args.req)
if (err != nil) != tt.wantErr {
diff --git a/deployment/keystone/changeset/internal/deploy.go b/deployment/keystone/changeset/internal/deploy.go
index 8b67013aa15..eed83f24e44 100644
--- a/deployment/keystone/changeset/internal/deploy.go
+++ b/deployment/keystone/changeset/internal/deploy.go
@@ -18,11 +18,12 @@ import (
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
chainsel "github.com/smartcontractkit/chain-selectors"
- capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
"golang.org/x/exp/maps"
"google.golang.org/protobuf/proto"
+ capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
+
"github.com/smartcontractkit/chainlink/deployment"
capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0"
@@ -323,12 +324,11 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []
}
_, err = configureOCR3contract(configureOCR3Request{
- cfg: cfg,
- chain: registryChain,
- contract: contract,
- nodes: don.Nodes,
- contractSet: &contracts,
- ocrSecrets: env.OCRSecrets,
+ cfg: cfg,
+ chain: registryChain,
+ contract: contract,
+ nodes: don.Nodes,
+ ocrSecrets: env.OCRSecrets,
})
if err != nil {
return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err)
@@ -386,14 +386,13 @@ func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3C
return nil, err
}
r, err := configureOCR3contract(configureOCR3Request{
- cfg: cfg.OCR3Config,
- chain: registryChain,
- contract: contract,
- nodes: nodes,
- dryRun: cfg.DryRun,
- contractSet: &contracts,
- useMCMS: cfg.UseMCMS,
- ocrSecrets: env.OCRSecrets,
+ cfg: cfg.OCR3Config,
+ chain: registryChain,
+ contract: contract,
+ nodes: nodes,
+ dryRun: cfg.DryRun,
+ useMCMS: cfg.UseMCMS,
+ ocrSecrets: env.OCRSecrets,
})
if err != nil {
return nil, err
@@ -514,8 +513,8 @@ type RegisterNOPSRequest struct {
}
type RegisterNOPSResponse struct {
- Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded
- Ops *timelock.BatchChainOperation
+ Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded // if UseMCMS is false, a list of added node operators is returned
+ Ops *timelock.BatchChainOperation // if UseMCMS is true, a batch proposal is returned and no transaction is confirmed on chain.
}
func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSRequest) (*RegisterNOPSResponse, error) {
@@ -668,16 +667,21 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
}
nodeIDToParams := make(map[string]capabilities_registry.CapabilitiesRegistryNodeParams)
+ nodeIDToDon := make(map[string]string)
for don, nodes := range req.DonToNodes {
caps, ok := req.DonToCapabilities[don]
if !ok {
return nil, fmt.Errorf("capabilities not found for don %s", don)
}
- var hashedCapabilityIds [][32]byte
+ var (
+ hashedCapabilityIDs [][32]byte
+ capIDs []string
+ )
for _, cap := range caps {
- hashedCapabilityIds = append(hashedCapabilityIds, cap.ID)
+ hashedCapabilityIDs = append(hashedCapabilityIDs, cap.ID)
+ capIDs = append(capIDs, hex.EncodeToString(cap.ID[:]))
}
- lggr.Debugw("hashed capability ids", "don", don, "ids", hashedCapabilityIds)
+ lggr.Debugw("hashed capability ids", "don", don, "ids", capIDs)
for _, n := range nodes {
if n.IsBootstrap { // bootstraps are part of the DON but don't host capabilities
@@ -703,37 +707,50 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
Signer: signer,
P2pId: n.PeerID,
EncryptionPublicKey: csakey,
- HashedCapabilityIds: hashedCapabilityIds,
+ 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 {
+ var newCapIDs [][32]byte
+ for _, proposedCapID := range hashedCapabilityIDs {
shouldAdd := true
- for _, existingCapId := range params.HashedCapabilityIds {
- if existingCapId == proposedCapId {
+ for _, existingCapID := range params.HashedCapabilityIds {
+ if existingCapID == proposedCapID {
shouldAdd = false
break
}
}
if shouldAdd {
- newCapIds = append(newCapIds, proposedCapId)
+ newCapIDs = append(newCapIDs, proposedCapID)
}
}
- params.HashedCapabilityIds = append(params.HashedCapabilityIds, newCapIds...)
+ params.HashedCapabilityIds = append(params.HashedCapabilityIds, newCapIDs...)
}
nodeIDToParams[n.NodeID] = params
+ nodeIDToDon[n.NodeID] = don
}
}
- var uniqueNodeParams []capabilities_registry.CapabilitiesRegistryNodeParams
- for _, v := range nodeIDToParams {
- uniqueNodeParams = append(uniqueNodeParams, v)
+ lggr.Debugw("checking for existing nodes", "count", len(nodeIDToParams))
+
+ nodes2Add, err := getNodesToRegister(registry, nodeIDToParams)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get nodes to register: %w", err)
}
- lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams)
+
+ lggr.Debugf("found %d missing nodes", len(nodes2Add))
+
+ if len(nodes2Add) == 0 {
+ lggr.Debug("no new nodes to register")
+ return &RegisterNodesResponse{
+ nodeIDToParams: nodeIDToParams,
+ }, nil
+ }
+
+ lggr.Debugw("unique node params to add after deduplication", "count", len(nodes2Add), "params", nodes2Add)
if req.UseMCMS {
- ops, err := addNodesMCMSProposal(registry, uniqueNodeParams, registryChain)
+ ops, err := addNodesMCMSProposal(registry, nodes2Add, registryChain)
if err != nil {
return nil, fmt.Errorf("failed to generate proposal to add nodes: %w", err)
}
@@ -744,7 +761,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
}, nil
}
- tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams)
+ tx, err := registry.AddNodes(registryChain.DeployerKey, nodes2Add)
if err != nil {
err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)
// no typed errors in the abi, so we have to do string matching
@@ -753,7 +770,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
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 {
+ for _, singleNodeParams := range nodes2Add {
tx, err = registry.AddNodes(registryChain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeParams{singleNodeParams})
if err != nil {
err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)
@@ -783,6 +800,34 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode
}, nil
}
+// getNodesToRegister returns the nodes that are not already registered in the registry
+func getNodesToRegister(
+ registry *capabilities_registry.CapabilitiesRegistry,
+ nodeIDToParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams,
+) ([]capabilities_registry.CapabilitiesRegistryNodeParams, error) {
+ nodes2Add := make([]capabilities_registry.CapabilitiesRegistryNodeParams, 0)
+ for nodeID, nodeParams := range nodeIDToParams {
+ var (
+ ni capabilities_registry.INodeInfoProviderNodeInfo
+ err error
+ )
+ if ni, err = registry.GetNode(&bind.CallOpts{}, nodeParams.P2pId); err != nil {
+ if err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err); strings.Contains(err.Error(), "NodeDoesNotExist") {
+ nodes2Add = append(nodes2Add, nodeParams)
+ continue
+ }
+ return nil, fmt.Errorf("failed to call GetNode for node %s: %w", nodeID, err)
+ }
+
+ // if no error, but node info is empty, then the node does not exist and should be added.
+ if hex.EncodeToString(ni.P2pId[:]) != hex.EncodeToString(nodeParams.P2pId[:]) && hex.EncodeToString(ni.P2pId[:]) == "0000000000000000000000000000000000000000000000000000000000000000" {
+ nodes2Add = append(nodes2Add, nodeParams)
+ continue
+ }
+ }
+ return nodes2Add, nil
+}
+
// addNodesMCMSProposal generates a single call to AddNodes for all the node params at once.
func addNodesMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, params []capabilities_registry.CapabilitiesRegistryNodeParams, regChain deployment.Chain) (*timelock.BatchChainOperation, error) {
tx, err := registry.AddNodes(deployment.SimTransactOpts(), params)
@@ -857,7 +902,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
}
lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs))
- mcmsOps := make([]mcms.Operation, 0, len(req.DonsToRegister))
+ mcmsOps := make([]mcms.Operation, 0)
for _, don := range req.DonsToRegister {
var p2pIds [][32]byte
for _, n := range don.Nodes {
@@ -908,6 +953,8 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
txOpts = deployment.SimTransactOpts()
}
+ lggr.Debugw("calling add don", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F,
+ "p2pids", p2pIds, "node count", len(p2pIds))
tx, err := registry.AddDON(txOpts, p2pIds, cfgs, true, wfSupported, don.F)
if err != nil {
err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)
@@ -934,12 +981,15 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes
}
if req.UseMCMS {
- return &RegisterDonsResponse{
- Ops: &timelock.BatchChainOperation{
- ChainIdentifier: mcms.ChainIdentifier(registryChain.Selector),
- Batch: mcmsOps,
- },
- }, nil
+ if len(mcmsOps) > 0 {
+ return &RegisterDonsResponse{
+ Ops: &timelock.BatchChainOperation{
+ ChainIdentifier: mcms.ChainIdentifier(registryChain.Selector),
+ Batch: mcmsOps,
+ },
+ }, nil
+ }
+ return &RegisterDonsResponse{}, nil
}
lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons)
@@ -996,12 +1046,11 @@ func containsAllDONs(donInfos []capabilities_registry.CapabilitiesRegistryDONInf
// 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(lggr logger.Logger, chain deployment.Chain, contractSet ContractSet, dons []RegisteredDon, useMCMS bool) (map[uint64]timelock.BatchChainOperation, error) {
- if contractSet.Forwarder == nil {
+func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon, useMCMS bool) (map[uint64]timelock.BatchChainOperation, error) {
+ if fwdr == nil {
return nil, errors.New("nil forwarder contract")
}
var (
- fwdr = contractSet.Forwarder
opMap = make(map[uint64]timelock.BatchChainOperation)
)
for _, dn := range dons {
diff --git a/deployment/keystone/changeset/internal/deploy_test.go b/deployment/keystone/changeset/internal/deploy_test.go
index c059cd5a981..83fcfe20e40 100644
--- a/deployment/keystone/changeset/internal/deploy_test.go
+++ b/deployment/keystone/changeset/internal/deploy_test.go
@@ -6,12 +6,14 @@ import (
"github.com/stretchr/testify/require"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
+ chain_selectors "github.com/smartcontractkit/chain-selectors"
+ "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+ kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
+ "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)
func Test_RegisterNOPS(t *testing.T) {
@@ -19,7 +21,7 @@ func Test_RegisterNOPS(t *testing.T) {
useMCMS bool
lggr = logger.Test(t)
setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{})
- registry = setupResp.Registry
+ registry = setupResp.CapabilitiesRegistry
chain = setupResp.Chain
nops = make([]kcr.CapabilitiesRegistryNodeOperator, 0)
)
@@ -59,7 +61,7 @@ func Test_AddCapabilities(t *testing.T) {
useMCMS bool
lggr = logger.Test(t)
setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{})
- registry = setupResp.Registry
+ registry = setupResp.CapabilitiesRegistry
chain = setupResp.Chain
capabilities = make([]kcr.CapabilitiesRegistryCapability, 0)
)
@@ -86,13 +88,71 @@ func Test_AddCapabilities(t *testing.T) {
func Test_RegisterNodes(t *testing.T) {
var (
- useMCMS bool
- lggr = logger.Test(t)
- setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{})
- registry = setupResp.Registry
- chain = setupResp.Chain
+ useMCMS bool
+ lggr = logger.Test(t)
+ existingNOP = testNop(t, "testNop")
+ initialp2pToCapabilities = map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{
+ testPeerID(t, "0x1"): {
+ {
+ LabelledName: "test",
+ Version: "1.0.0",
+ CapabilityType: 0,
+ },
+ },
+ }
+ nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
+ existingNOP: {
+ {
+ Signer: [32]byte{0: 1},
+ P2PKey: testPeerID(t, "0x1"),
+ EncryptionPublicKey: [32]byte{3: 16, 4: 2},
+ },
+ },
+ }
+
+ setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{
+ P2pToCapabilities: initialp2pToCapabilities,
+ NopToNodes: nopToNodes,
+ })
+ registry = setupResp.CapabilitiesRegistry
+ chain = setupResp.Chain
+
+ registeredCapabilities = kstest.GetRegisteredCapabilities(t, lggr, initialp2pToCapabilities, setupResp.CapabilityCache)
+
+ registeredNodeParams = kstest.ToNodeParams(t, nopToNodes,
+ kstest.ToP2PToCapabilities(t, initialp2pToCapabilities, registry, registeredCapabilities),
+ )
)
t.Run("success create add nodes mcms proposal", func(t *testing.T) {
+ var (
+ nop2Add = testNop(t, "newNop")
+ caps2Add = map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{
+ testPeerID(t, "0x2"): {
+ {
+ LabelledName: "new-cap",
+ Version: "1.0.0",
+ CapabilityType: 0,
+ },
+ },
+ }
+
+ nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
+ nop2Add: {
+ {
+ Signer: [32]byte{0: 1},
+ P2PKey: testPeerID(t, "0x2"),
+ EncryptionPublicKey: [32]byte{3: 16, 4: 2},
+ },
+ },
+ }
+
+ rc, _ = kstest.MustAddCapabilities(t, lggr, caps2Add, chain, registry)
+
+ nps = kstest.ToNodeParams(t, nopToNodes,
+ kstest.ToP2PToCapabilities(t, caps2Add, registry, rc),
+ )
+ )
+
useMCMS = true
env := &deployment.Environment{
Logger: lggr,
@@ -112,11 +172,109 @@ func Test_RegisterNodes(t *testing.T) {
Env: env,
RegistryChainSelector: chain.Selector,
UseMCMS: useMCMS,
+ DonToCapabilities: map[string][]internal.RegisteredCapability{
+ "testDON": rc,
+ },
+ NopToNodeIDs: map[kcr.CapabilitiesRegistryNodeOperator][]string{
+ nop2Add: {"node-id"},
+ },
+ DonToNodes: map[string][]deployment.Node{
+ "testDON": {
+ {
+ PeerID: nps[0].P2pId,
+ NodeID: "node-id",
+ SelToOCRConfig: map[chain_selectors.ChainDetails]deployment.OCRConfig{
+ {
+ ChainSelector: chain.Selector,
+ }: {},
+ },
+ },
+ },
+ },
+ Nops: []*kcr.CapabilitiesRegistryNodeOperatorAdded{{
+ Name: nop2Add.Name,
+ Admin: nop2Add.Admin,
+ NodeOperatorId: 2,
+ }},
})
require.NoError(t, err)
require.NotNil(t, resp.Ops)
require.Len(t, resp.Ops.Batch, 1)
})
+
+ t.Run("no ops in proposal if node already exists", func(t *testing.T) {
+ useMCMS = true
+ env := &deployment.Environment{
+ Logger: lggr,
+ Chains: map[uint64]deployment.Chain{
+ chain.Selector: chain,
+ },
+ ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{
+ chain.Selector: {
+ registry.Address().String(): deployment.TypeAndVersion{
+ Type: internal.CapabilitiesRegistry,
+ Version: deployment.Version1_0_0,
+ },
+ },
+ }),
+ }
+ resp, err := internal.RegisterNodes(lggr, &internal.RegisterNodesRequest{
+ Env: env,
+ RegistryChainSelector: chain.Selector,
+ UseMCMS: useMCMS,
+ DonToCapabilities: map[string][]internal.RegisteredCapability{
+ "testDON": registeredCapabilities,
+ },
+ NopToNodeIDs: map[kcr.CapabilitiesRegistryNodeOperator][]string{
+ existingNOP: {"node-id"},
+ },
+ DonToNodes: map[string][]deployment.Node{
+ "testDON": {
+ {
+ PeerID: registeredNodeParams[0].P2pId,
+ NodeID: "node-id",
+ SelToOCRConfig: map[chain_selectors.ChainDetails]deployment.OCRConfig{
+ {
+ ChainSelector: chain.Selector,
+ }: {},
+ },
+ },
+ },
+ },
+ Nops: []*kcr.CapabilitiesRegistryNodeOperatorAdded{{
+ Name: existingNOP.Name,
+ Admin: existingNOP.Admin,
+ NodeOperatorId: 1,
+ }},
+ })
+ require.NoError(t, err)
+ require.Nil(t, resp.Ops)
+ })
+
+ t.Run("no new nodes to add results in no mcms ops", func(t *testing.T) {
+ useMCMS = true
+ env := &deployment.Environment{
+ Logger: lggr,
+ Chains: map[uint64]deployment.Chain{
+ chain.Selector: chain,
+ },
+ ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{
+ chain.Selector: {
+ registry.Address().String(): deployment.TypeAndVersion{
+ Type: internal.CapabilitiesRegistry,
+ Version: deployment.Version1_0_0,
+ },
+ },
+ }),
+ }
+ resp, err := internal.RegisterNodes(lggr, &internal.RegisterNodesRequest{
+ Env: env,
+ RegistryChainSelector: chain.Selector,
+ UseMCMS: useMCMS,
+ })
+ require.NoError(t, err)
+ require.Nil(t, resp.Ops)
+ })
}
func Test_RegisterDons(t *testing.T) {
@@ -124,7 +282,7 @@ func Test_RegisterDons(t *testing.T) {
useMCMS bool
lggr = logger.Test(t)
setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{})
- registry = setupResp.Registry
+ registry = setupResp.CapabilitiesRegistry
chain = setupResp.Chain
)
t.Run("success create add DONs mcms proposal", func(t *testing.T) {
@@ -162,6 +320,98 @@ func Test_RegisterDons(t *testing.T) {
require.Len(t, resp.Ops.Batch, 1)
})
+ t.Run("no new dons to add results in no mcms ops", func(t *testing.T) {
+ var (
+ existingNOP = testNop(t, "testNop")
+ existingP2Pkey = testPeerID(t, "0x1")
+ initialp2pToCapabilities = map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{
+ existingP2Pkey: {
+ {
+ LabelledName: "test",
+ Version: "1.0.0",
+ CapabilityType: 0,
+ },
+ },
+ testPeerID(t, "0x2"): {
+ {
+ LabelledName: "test",
+ Version: "1.0.0",
+ CapabilityType: 0,
+ },
+ },
+ testPeerID(t, "0x3"): {
+ {
+ LabelledName: "test",
+ Version: "1.0.0",
+ CapabilityType: 0,
+ },
+ },
+ }
+ nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
+ existingNOP: {
+ {
+ Signer: [32]byte{0: 1},
+ P2PKey: existingP2Pkey,
+ EncryptionPublicKey: [32]byte{3: 16, 4: 2},
+ },
+ {
+ Signer: [32]byte{0: 1, 1: 1},
+ P2PKey: testPeerID(t, "0x2"),
+ EncryptionPublicKey: [32]byte{3: 16, 4: 2},
+ },
+ {
+ Signer: [32]byte{0: 1, 1: 1, 2: 1},
+ P2PKey: testPeerID(t, "0x3"),
+ EncryptionPublicKey: [32]byte{3: 16, 4: 2},
+ },
+ },
+ }
+
+ setupResp = kstest.SetupTestRegistry(t, lggr, &kstest.SetupTestRegistryRequest{
+ P2pToCapabilities: initialp2pToCapabilities,
+ NopToNodes: nopToNodes,
+ Dons: []kstest.Don{
+ {
+ Name: "test-don",
+ P2PIDs: []p2pkey.PeerID{existingP2Pkey, testPeerID(t, "0x2"), testPeerID(t, "0x3")},
+ },
+ },
+ })
+ regContract = setupResp.CapabilitiesRegistry
+ )
+
+ env := &deployment.Environment{
+ Logger: lggr,
+ Chains: map[uint64]deployment.Chain{
+ setupResp.Chain.Selector: setupResp.Chain,
+ },
+ ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{
+ setupResp.Chain.Selector: {
+ regContract.Address().String(): deployment.TypeAndVersion{
+ Type: internal.CapabilitiesRegistry,
+ Version: deployment.Version1_0_0,
+ },
+ },
+ }),
+ }
+ resp, err := internal.RegisterDons(lggr, internal.RegisterDonsRequest{
+ Env: env,
+ RegistryChainSelector: setupResp.Chain.Selector,
+ DonToCapabilities: map[string][]internal.RegisteredCapability{
+ "test-don": {},
+ },
+ DonsToRegister: []internal.DONToRegister{
+ {
+ Name: "test-don",
+ F: 1,
+ },
+ },
+ UseMCMS: true,
+ })
+ require.NoError(t, err)
+ require.Nil(t, resp.Ops)
+ })
+
t.Run("success create add DONs mcms proposal with multiple DONs", func(t *testing.T) {
useMCMS = true
env := &deployment.Environment{
diff --git a/deployment/keystone/changeset/internal/forwarder_deployer.go b/deployment/keystone/changeset/internal/forwarder_deployer.go
index 6e374e200d7..90a3e8cfb1d 100644
--- a/deployment/keystone/changeset/internal/forwarder_deployer.go
+++ b/deployment/keystone/changeset/internal/forwarder_deployer.go
@@ -88,7 +88,7 @@ func ConfigureForwardContracts(env *deployment.Environment, req ConfigureForward
if !ok {
return nil, fmt.Errorf("failed to get contract set for chain %d", chain.Selector)
}
- ops, err := configureForwarder(env.Logger, chain, contracts, req.Dons, req.UseMCMS)
+ ops, err := configureForwarder(env.Logger, chain, contracts.Forwarder, req.Dons, req.UseMCMS)
if err != nil {
return nil, fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err)
}
diff --git a/deployment/keystone/changeset/internal/ocr3config.go b/deployment/keystone/changeset/internal/ocr3config.go
index d1d2e337efb..8b433189081 100644
--- a/deployment/keystone/changeset/internal/ocr3config.go
+++ b/deployment/keystone/changeset/internal/ocr3config.go
@@ -287,8 +287,7 @@ type configureOCR3Request struct {
dryRun bool
ocrSecrets deployment.OCRSecrets
- useMCMS bool
- contractSet *ContractSet
+ useMCMS bool
}
func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) {
diff --git a/deployment/keystone/changeset/internal/state.go b/deployment/keystone/changeset/internal/state.go
index 3253acaf4e4..ad81d912d0d 100644
--- a/deployment/keystone/changeset/internal/state.go
+++ b/deployment/keystone/changeset/internal/state.go
@@ -27,6 +27,7 @@ type GetContractSetsResponse struct {
ContractSets map[uint64]ContractSet
}
+// TODO move this out of internal
type ContractSet struct {
commonchangeset.MCMSWithTimelockState
OCR3 map[common.Address]*ocr3_capability.OCR3Capability
diff --git a/deployment/keystone/changeset/internal/types.go b/deployment/keystone/changeset/internal/types.go
index c4e9deccdf9..d803a652c5f 100644
--- a/deployment/keystone/changeset/internal/types.go
+++ b/deployment/keystone/changeset/internal/types.go
@@ -10,6 +10,7 @@ import (
"strings"
"github.com/ethereum/go-ethereum/common"
+
capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb"
chainsel "github.com/smartcontractkit/chain-selectors"
@@ -23,7 +24,7 @@ import (
var (
CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392
- WorkflowRegistry deployment.ContractType = "WorkflowRegistry" // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol
+ WorkflowRegistry deployment.ContractType = "WorkflowRegistry" // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/workflow/WorkflowRegistry.sol
KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90
OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12
FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1
@@ -255,6 +256,10 @@ func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*Reg
}
capReg := r.ContractSets[cfg.RegistryChainSel].CapabilitiesRegistry
+ if capReg == nil {
+ return nil, errors.New("capabilities registry not found in contract sets")
+ }
+
di, err := capReg.GetDONs(nil)
if err != nil {
return nil, fmt.Errorf("failed to get dons: %w", err)
diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go
index b5006358f77..965f926da31 100644
--- a/deployment/keystone/changeset/internal/update_don.go
+++ b/deployment/keystone/changeset/internal/update_don.go
@@ -14,6 +14,7 @@ import (
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
+
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/deployment"
@@ -28,8 +29,8 @@ type CapabilityConfig struct {
}
type UpdateDonRequest struct {
- Chain deployment.Chain
- ContractSet *ContractSet // contract set for the given chain
+ Chain deployment.Chain
+ CapabilitiesRegistry *kcr.CapabilitiesRegistry
P2PIDs []p2pkey.PeerID // this is the unique identifier for the don
CapabilityConfigs []CapabilityConfig // if Config subfield is nil, a default config is used
@@ -39,10 +40,10 @@ type UpdateDonRequest struct {
func (r *UpdateDonRequest) AppendNodeCapabilitiesRequest() *AppendNodeCapabilitiesRequest {
out := &AppendNodeCapabilitiesRequest{
- Chain: r.Chain,
- ContractSet: r.ContractSet,
- P2pToCapabilities: make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability),
- UseMCMS: r.UseMCMS,
+ Chain: r.Chain,
+ CapabilitiesRegistry: r.CapabilitiesRegistry,
+ P2pToCapabilities: make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability),
+ UseMCMS: r.UseMCMS,
}
for _, p2pid := range r.P2PIDs {
if _, exists := out.P2pToCapabilities[p2pid]; !exists {
@@ -56,7 +57,7 @@ func (r *UpdateDonRequest) AppendNodeCapabilitiesRequest() *AppendNodeCapabiliti
}
func (r *UpdateDonRequest) Validate() error {
- if r.ContractSet.CapabilitiesRegistry == nil {
+ if r.CapabilitiesRegistry == nil {
return errors.New("registry is required")
}
if len(r.P2PIDs) == 0 {
@@ -75,7 +76,7 @@ func UpdateDon(_ logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, erro
return nil, fmt.Errorf("failed to validate request: %w", err)
}
- registry := req.ContractSet.CapabilitiesRegistry
+ registry := req.CapabilitiesRegistry
getDonsResp, err := registry.GetDONs(&bind.CallOpts{})
if err != nil {
return nil, fmt.Errorf("failed to get Dons: %w", err)
diff --git a/deployment/keystone/changeset/internal/update_don_test.go b/deployment/keystone/changeset/internal/update_don_test.go
index 42b032d9433..7fbdcda100d 100644
--- a/deployment/keystone/changeset/internal/update_don_test.go
+++ b/deployment/keystone/changeset/internal/update_don_test.go
@@ -20,7 +20,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment"
kscs "github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+ kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)
@@ -131,16 +131,16 @@ func TestUpdateDon(t *testing.T) {
}
_, err := internal.AppendNodeCapabilitiesImpl(lggr, &internal.AppendNodeCapabilitiesRequest{
- Chain: testCfg.Chain,
- ContractSet: testCfg.ContractSet,
- P2pToCapabilities: m,
+ Chain: testCfg.Chain,
+ CapabilitiesRegistry: testCfg.CapabilitiesRegistry,
+ P2pToCapabilities: m,
})
require.NoError(t, err)
req := &internal.UpdateDonRequest{
- ContractSet: testCfg.ContractSet,
- Chain: testCfg.Chain,
- P2PIDs: []p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()},
+ CapabilitiesRegistry: testCfg.CapabilitiesRegistry,
+ Chain: testCfg.Chain,
+ P2PIDs: []p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()},
CapabilityConfigs: []internal.CapabilityConfig{
{Capability: initialCap, Config: initialCapCfgB}, {Capability: capToAdd, Config: capToAddCfgB},
},
@@ -151,8 +151,8 @@ func TestUpdateDon(t *testing.T) {
ConfigCount: 1,
NodeP2PIds: internal.PeerIDsToBytes([]p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}),
CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{
- {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, initialCap), Config: initialCapCfgB},
- {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, capToAdd), Config: capToAddCfgB},
+ {CapabilityId: kstest.MustCapabilityId(t, testCfg.CapabilitiesRegistry, initialCap), Config: initialCapCfgB},
+ {CapabilityId: kstest.MustCapabilityId(t, testCfg.CapabilitiesRegistry, capToAdd), Config: capToAddCfgB},
},
},
}
diff --git a/deployment/keystone/changeset/internal/update_node_capabilities.go b/deployment/keystone/changeset/internal/update_node_capabilities.go
index 34fb5346d5c..ce975368a1d 100644
--- a/deployment/keystone/changeset/internal/update_node_capabilities.go
+++ b/deployment/keystone/changeset/internal/update_node_capabilities.go
@@ -11,9 +11,9 @@ import (
)
type UpdateNodeCapabilitiesImplRequest struct {
- Chain deployment.Chain
- ContractSet *ContractSet
- P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability
+ Chain deployment.Chain
+ CapabilitiesRegistry *kcr.CapabilitiesRegistry
+ P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability
UseMCMS bool
}
@@ -22,7 +22,7 @@ func (req *UpdateNodeCapabilitiesImplRequest) Validate() error {
if len(req.P2pToCapabilities) == 0 {
return errors.New("p2pToCapabilities is empty")
}
- if req.ContractSet == nil {
+ if req.CapabilitiesRegistry == nil {
return errors.New("registry is nil")
}
@@ -38,7 +38,7 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI
for _, cap := range req.P2pToCapabilities {
capabilities = append(capabilities, cap...)
}
- op, err := AddCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS)
+ op, err := AddCapabilities(lggr, req.CapabilitiesRegistry, req.Chain, capabilities, req.UseMCMS)
if err != nil {
return nil, fmt.Errorf("failed to add capabilities: %w", err)
}
@@ -49,11 +49,11 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI
}
updateNodesReq := &UpdateNodesRequest{
- Chain: req.Chain,
- P2pToUpdates: p2pToUpdates,
- ContractSet: req.ContractSet,
- Ops: op,
- UseMCMS: req.UseMCMS,
+ Chain: req.Chain,
+ P2pToUpdates: p2pToUpdates,
+ CapabilitiesRegistry: req.CapabilitiesRegistry,
+ Ops: op,
+ UseMCMS: req.UseMCMS,
}
resp, err := UpdateNodes(lggr, updateNodesReq)
if err != nil {
diff --git a/deployment/keystone/changeset/internal/update_node_capabilities_test.go b/deployment/keystone/changeset/internal/update_node_capabilities_test.go
index 65da264dd01..560494ba09e 100644
--- a/deployment/keystone/changeset/internal/update_node_capabilities_test.go
+++ b/deployment/keystone/changeset/internal/update_node_capabilities_test.go
@@ -9,7 +9,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+ kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)
@@ -93,7 +93,7 @@ func TestUpdateNodeCapabilities(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
setupResp := kstest.SetupTestRegistry(t, lggr, tt.args.initialState)
tt.args.req.Chain = setupResp.Chain
- tt.args.req.ContractSet = setupResp.ContractSet
+ tt.args.req.CapabilitiesRegistry = setupResp.CapabilitiesRegistry
got, err := internal.UpdateNodeCapabilitiesImpl(tt.args.lggr, tt.args.req)
if (err != nil) != tt.wantErr {
diff --git a/deployment/keystone/changeset/internal/update_nodes.go b/deployment/keystone/changeset/internal/update_nodes.go
index 976125e582d..4c33b3d08a3 100644
--- a/deployment/keystone/changeset/internal/update_nodes.go
+++ b/deployment/keystone/changeset/internal/update_nodes.go
@@ -29,8 +29,8 @@ type NodeUpdate struct {
}
type UpdateNodesRequest struct {
- Chain deployment.Chain
- ContractSet *ContractSet // contract set for the given chain
+ Chain deployment.Chain
+ CapabilitiesRegistry *kcr.CapabilitiesRegistry
P2pToUpdates map[p2pkey.PeerID]NodeUpdate
@@ -41,7 +41,7 @@ type UpdateNodesRequest struct {
}
func (req *UpdateNodesRequest) NodeParams() ([]kcr.CapabilitiesRegistryNodeParams, error) {
- return makeNodeParams(req.ContractSet.CapabilitiesRegistry, req.P2pToUpdates)
+ return makeNodeParams(req.CapabilitiesRegistry, req.P2pToUpdates)
}
// P2PSignerEnc represent the key fields in kcr.CapabilitiesRegistryNodeParams
@@ -79,7 +79,7 @@ func (req *UpdateNodesRequest) Validate() error {
}
}
- if req.ContractSet.CapabilitiesRegistry == nil {
+ if req.CapabilitiesRegistry == nil {
return errors.New("registry is nil")
}
@@ -110,7 +110,7 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo
if req.UseMCMS {
txOpts = deployment.SimTransactOpts()
}
- registry := req.ContractSet.CapabilitiesRegistry
+ registry := req.CapabilitiesRegistry
tx, err := registry.UpdateNodes(txOpts, params)
if err != nil {
err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err)
diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go
index 642eaebbe4d..c26c57ab4f6 100644
--- a/deployment/keystone/changeset/internal/update_nodes_test.go
+++ b/deployment/keystone/changeset/internal/update_nodes_test.go
@@ -22,17 +22,17 @@ import (
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+ kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
)
func Test_UpdateNodesRequest_validate(t *testing.T) {
type fields struct {
- p2pToUpdates map[p2pkey.PeerID]internal.NodeUpdate
- nopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc
- chain deployment.Chain
- contractSet *internal.ContractSet
+ p2pToUpdates map[p2pkey.PeerID]internal.NodeUpdate
+ nopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc
+ chain deployment.Chain
+ capabilitiesRegistry *kcr.CapabilitiesRegistry
}
tests := []struct {
name string
@@ -42,10 +42,10 @@ func Test_UpdateNodesRequest_validate(t *testing.T) {
{
name: "err",
fields: fields{
- p2pToUpdates: map[p2pkey.PeerID]internal.NodeUpdate{},
- nopToNodes: nil,
- chain: deployment.Chain{},
- contractSet: nil,
+ p2pToUpdates: map[p2pkey.PeerID]internal.NodeUpdate{},
+ nopToNodes: nil,
+ chain: deployment.Chain{},
+ capabilitiesRegistry: nil,
},
wantErr: true,
},
@@ -57,9 +57,9 @@ func Test_UpdateNodesRequest_validate(t *testing.T) {
EncryptionPublicKey: "jk",
},
},
- nopToNodes: nil,
- chain: deployment.Chain{},
- contractSet: nil,
+ nopToNodes: nil,
+ chain: deployment.Chain{},
+ capabilitiesRegistry: nil,
},
wantErr: true,
},
@@ -71,9 +71,9 @@ func Test_UpdateNodesRequest_validate(t *testing.T) {
EncryptionPublicKey: "aabb",
},
},
- nopToNodes: nil,
- chain: deployment.Chain{},
- contractSet: nil,
+ nopToNodes: nil,
+ chain: deployment.Chain{},
+ capabilitiesRegistry: nil,
},
wantErr: true,
},
@@ -81,9 +81,9 @@ func Test_UpdateNodesRequest_validate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := &internal.UpdateNodesRequest{
- P2pToUpdates: tt.fields.p2pToUpdates,
- Chain: tt.fields.chain,
- ContractSet: tt.fields.contractSet,
+ P2pToUpdates: tt.fields.p2pToUpdates,
+ Chain: tt.fields.chain,
+ CapabilitiesRegistry: tt.fields.capabilitiesRegistry,
}
if err := req.Validate(); (err != nil) != tt.wantErr {
t.Errorf("internal.UpdateNodesRequest.validate() error = %v, wantErr %v", err, tt.wantErr)
@@ -276,12 +276,13 @@ func TestUpdateNodes(t *testing.T) {
wantErr: false,
},
{
- name: "twos node, different capabilities",
+ name: "twos nodes with different capabilities",
args: args{
lggr: lggr,
req: &internal.UpdateNodesRequest{
P2pToUpdates: map[p2pkey.PeerID]internal.NodeUpdate{
- testPeerID(t, "peerID_1"): internal.NodeUpdate{
+ testPeerID(t, "peerID_1"): {
+ NodeOperatorID: 1,
Capabilities: []kcr.CapabilitiesRegistryCapability{
{
LabelledName: "cap1",
@@ -290,7 +291,8 @@ func TestUpdateNodes(t *testing.T) {
},
},
},
- testPeerID(t, "peerID_2"): internal.NodeUpdate{
+ testPeerID(t, "peerID_2"): {
+ NodeOperatorID: 2,
Capabilities: []kcr.CapabilitiesRegistryCapability{
{
LabelledName: "cap2",
@@ -303,14 +305,14 @@ func TestUpdateNodes(t *testing.T) {
Chain: chain,
},
nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
- testNop(t, "nopA"): []*internal.P2PSignerEnc{
+ testNop(t, "nopA"): {
{
P2PKey: testPeerID(t, "peerID_1"),
Signer: [32]byte{0: 1, 31: 1},
EncryptionPublicKey: [32]byte{0: 7, 1: 7},
},
},
- testNop(t, "nopB"): []*internal.P2PSignerEnc{
+ testNop(t, "nopB"): {
{
P2PKey: testPeerID(t, "peerID_2"),
Signer: [32]byte{0: 2, 31: 2},
@@ -349,8 +351,8 @@ func TestUpdateNodes(t *testing.T) {
EncryptionPublicKey: newKeyStr,
},
},
- Chain: chain,
- ContractSet: nil, // set in test to ensure no conflicts
+ Chain: chain,
+ CapabilitiesRegistry: nil, // set in test to ensure no conflicts
},
nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
testNop(t, "nop1"): []*internal.P2PSignerEnc{
@@ -384,8 +386,8 @@ func TestUpdateNodes(t *testing.T) {
Signer: [32]byte{0: 2, 1: 3},
},
},
- Chain: chain,
- ContractSet: nil, // set in test to ensure no conflicts
+ Chain: chain,
+ CapabilitiesRegistry: nil, // set in test to ensure no conflicts
},
nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{
testNop(t, "nop1"): []*internal.P2PSignerEnc{
@@ -471,8 +473,8 @@ func TestUpdateNodes(t *testing.T) {
P2pToCapabilities: initMap,
NopToNodes: tt.args.nopsToNodes,
})
- registry := setupResp.Registry
- tt.args.req.ContractSet = setupResp.ContractSet
+ registry := setupResp.CapabilitiesRegistry
+ tt.args.req.CapabilitiesRegistry = setupResp.CapabilitiesRegistry
tt.args.req.Chain = setupResp.Chain
id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, phonyCap.LabelledName, phonyCap.Version)
@@ -496,12 +498,12 @@ func TestUpdateNodes(t *testing.T) {
t.Errorf("UpdateNodes() error = %v, wantErr %v", err, tt.wantErr)
return
}
- for i, p := range got.NodeParams {
- expected := tt.want.NodeParams[i]
- require.Equal(t, expected.NodeOperatorId, p.NodeOperatorId)
- require.Equal(t, expected.P2pId, p.P2pId)
- require.Equal(t, expected.Signer, p.Signer)
- require.Equal(t, expected.EncryptionPublicKey, p.EncryptionPublicKey)
+
+ for _, p := range got.NodeParams {
+ // check the node params
+ expected := findNodeParams(t, tt.want.NodeParams, p.P2pId)
+ assertNodeParams(t, expected, p)
+
// check the capabilities
expectedCaps := expectedUpdatedCaps[p.P2pId]
var wantHashedIDs [][32]byte
@@ -565,7 +567,7 @@ func TestUpdateNodes(t *testing.T) {
P2pToCapabilities: p2pToCapabilitiesInitial,
NopToNodes: nopToNodes,
})
- registry := setupResp.Registry
+ registry := setupResp.CapabilitiesRegistry
chain := setupResp.Chain
// there should be two capabilities
@@ -590,8 +592,8 @@ func TestUpdateNodes(t *testing.T) {
Capabilities: toRegister,
},
},
- Chain: chain,
- ContractSet: setupResp.ContractSet,
+ Chain: chain,
+ CapabilitiesRegistry: setupResp.CapabilitiesRegistry,
}
_, err = internal.UpdateNodes(lggr, req)
require.NoError(t, err)
@@ -639,7 +641,7 @@ func TestAppendCapabilities(t *testing.T) {
P2pToCapabilities: capMap,
NopToNodes: nopToNodes,
})
- registry := setupResp.Registry
+ registry := setupResp.CapabilitiesRegistry
chain := setupResp.Chain
info, err := registry.GetNode(&bind.CallOpts{}, testPeerID(t, "peerID_1"))
@@ -703,3 +705,21 @@ func testNop(t *testing.T, name string) kcr.CapabilitiesRegistryNodeOperator {
Name: name,
}
}
+
+func findNodeParams(t *testing.T, nodes []kcr.CapabilitiesRegistryNodeParams, p2p p2pkey.PeerID) kcr.CapabilitiesRegistryNodeParams {
+ for _, n := range nodes {
+ if n.P2pId == p2p {
+ return n
+ }
+ }
+ require.Failf(t, "could not find node %s", p2p.String())
+ return kcr.CapabilitiesRegistryNodeParams{}
+}
+
+func assertNodeParams(t *testing.T, expected, got kcr.CapabilitiesRegistryNodeParams) {
+ t.Helper()
+ assert.Equal(t, expected.P2pId, got.P2pId, "p2p ID failed : expected %v, got %v", expected.P2pId, got.P2pId)
+ assert.Equal(t, expected.NodeOperatorId, got.NodeOperatorId, "nop ID failed : expected %d, got %d", expected.NodeOperatorId, got.NodeOperatorId)
+ assert.Equal(t, expected.Signer, got.Signer, "signer failed : expected %v, got %v", expected.Signer, got.Signer)
+ assert.Equal(t, expected.EncryptionPublicKey, got.EncryptionPublicKey, "encryption key failed : expected %v, got %v", expected.EncryptionPublicKey, got.EncryptionPublicKey)
+}
diff --git a/deployment/keystone/changeset/test/helpers.go b/deployment/keystone/changeset/test/helpers.go
index 02f0f88d5dd..cb2f8c3b489 100644
--- a/deployment/keystone/changeset/test/helpers.go
+++ b/deployment/keystone/changeset/test/helpers.go
@@ -24,7 +24,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
@@ -138,22 +138,22 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv {
wfChains := map[uint64]deployment.Chain{}
wfChains[registryChainSel] = chains[registryChainSel]
- wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, c.WFDonConfig.N, 0, crConfig)
+ wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, nil, c.WFDonConfig.N, 0, crConfig)
require.Len(t, wfNodes, c.WFDonConfig.N)
writerChains := map[uint64]deployment.Chain{}
maps.Copy(writerChains, chains)
- cwNodes := memory.NewNodes(t, zapcore.InfoLevel, writerChains, c.WriterDonConfig.N, 0, crConfig)
+ cwNodes := memory.NewNodes(t, zapcore.InfoLevel, writerChains, nil, c.WriterDonConfig.N, 0, crConfig)
require.Len(t, cwNodes, c.WriterDonConfig.N)
assetChains := map[uint64]deployment.Chain{}
assetChains[registryChainSel] = chains[registryChainSel]
- assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, c.AssetDonConfig.N, 0, crConfig)
+ assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, nil, c.AssetDonConfig.N, 0, crConfig)
require.Len(t, assetNodes, c.AssetDonConfig.N)
- ocr3CapCfg := kstest.GetDefaultCapConfig(t, internal.OCR3Cap)
- writerChainCapCfg := kstest.GetDefaultCapConfig(t, internal.WriteChainCap)
- streamTriggerChainCapCfg := kstest.GetDefaultCapConfig(t, internal.StreamTriggerCap)
+ ocr3CapCfg := GetDefaultCapConfig(t, internal.OCR3Cap)
+ writerChainCapCfg := GetDefaultCapConfig(t, internal.WriteChainCap)
+ streamTriggerChainCapCfg := GetDefaultCapConfig(t, internal.StreamTriggerCap)
// TODO: partition nodes into multiple nops
@@ -201,7 +201,7 @@ func SetupTestEnv(t *testing.T, c TestConfig) TestEnv {
maps.Copy(allNodes, wfNodes)
maps.Copy(allNodes, cwNodes)
maps.Copy(allNodes, assetNodes)
- env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, allNodes)
+ env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, nil, allNodes)
// set the env addresses to the deployed addresses that were created prior to configuring the nodes
err = env.ExistingAddresses.Merge(e.ExistingAddresses)
require.NoError(t, err)
diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/test/registry.go
similarity index 67%
rename from deployment/keystone/changeset/internal/test/utils.go
rename to deployment/keystone/changeset/test/registry.go
index 290d0ee2196..9b1ce4ec8cc 100644
--- a/deployment/keystone/changeset/internal/test/utils.go
+++ b/deployment/keystone/changeset/test/registry.go
@@ -3,6 +3,7 @@ package test
import (
"context"
"fmt"
+ "maps"
"sort"
"testing"
"time"
@@ -30,81 +31,183 @@ type Don struct {
}
type SetupTestRegistryRequest struct {
+ // P2pToCapabilities maps a node's p2pID to the capabilities it has
P2pToCapabilities map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability
- NopToNodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc
- Dons []Don
+
+ // NopToNodes maps a node operator to the nodes they operate
+ NopToNodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc
+
+ // Dons groups the p2pIDs of the nodes that comprise it and the capabilities they have
+ Dons []Don
// TODO maybe add support for MCMS at this level
}
type SetupTestRegistryResponse struct {
- Registry *capabilities_registry.CapabilitiesRegistry
- Chain deployment.Chain
- RegistrySelector uint64
- ContractSet *internal.ContractSet
+ CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry
+ Chain deployment.Chain
+ RegistrySelector uint64
+ CapabilityCache *CapabilityCache
}
+// SetupTestRegistry deploys a capabilities registry to the given chain
+// and adds the given capabilities and node operators
+// It can be used in tests that mutate the registry without any other setup such as actual nodes, dons, jobs, etc.
func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryRequest) *SetupTestRegistryResponse {
chain := testChain(t)
+
// deploy the registry
registry := deployCapReg(t, chain)
+
// convert req to nodeoperators
+ nops := ToNodeOps(t, req.NopToNodes)
+ addNopsResp := addNops(t, lggr, chain, registry, nops)
+ require.Len(t, addNopsResp.Nops, len(nops))
+
+ // add capabilities to registry
+ registeredCapabilities, capCache := MustAddCapabilities(t, lggr, req.P2pToCapabilities, chain, registry)
+
+ // make the nodes and register node
+ nodeParams := ToNodeParams(t,
+ req.NopToNodes,
+ ToP2PToCapabilities(t, req.P2pToCapabilities, registry, registeredCapabilities),
+ )
+
+ AddNodes(t, lggr, chain, registry, nodeParams)
+
+ // add the Dons
+ addDons(t, lggr, chain, registry, capCache, req.Dons)
+
+ return &SetupTestRegistryResponse{
+ CapabilitiesRegistry: registry,
+ Chain: chain,
+ RegistrySelector: chain.Selector,
+ CapabilityCache: capCache,
+ }
+}
+
+// ToNodeParams transforms a map of node operators to nops and a map of node p2pID to capabilities
+// must match the number of nodes.
+// The order of returned nodeParams is deterministic and sorted by node operator name.
+func ToNodeParams(t *testing.T,
+ nop2Nodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc,
+ p2pToCapabilities map[p2pkey.PeerID][][32]byte,
+) []capabilities_registry.CapabilitiesRegistryNodeParams {
+ t.Helper()
+
+ var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams
+ var i uint32
+ // deterministic order
+ // get the keys of the map and sort them
+ var keys []capabilities_registry.CapabilitiesRegistryNodeOperator
+ for k := range maps.Keys(nop2Nodes) {
+ keys = append(keys, k)
+ }
+ sort.Slice(keys, func(i, j int) bool {
+ return keys[i].Name < keys[j].Name
+ })
+ for _, k := range keys {
+ p2pSignerEncs, ok := nop2Nodes[k]
+ require.True(t, ok, "missing node operator %s", k.Name)
+ for _, p2pSignerEnc := range p2pSignerEncs {
+ _, exists := p2pToCapabilities[p2pSignerEnc.P2PKey]
+ require.True(t, exists, "missing capabilities for p2pID %s", p2pSignerEnc.P2PKey)
+
+ nodeParams = append(nodeParams, capabilities_registry.CapabilitiesRegistryNodeParams{
+ Signer: p2pSignerEnc.Signer,
+ P2pId: p2pSignerEnc.P2PKey,
+ EncryptionPublicKey: p2pSignerEnc.EncryptionPublicKey,
+ HashedCapabilityIds: p2pToCapabilities[p2pSignerEnc.P2PKey],
+ NodeOperatorId: i + 1, // one-indexed
+ })
+ }
+ i++
+ }
+
+ return nodeParams
+}
+
+func ToNodeOps(
+ t *testing.T,
+ nop2Nodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc,
+) []capabilities_registry.CapabilitiesRegistryNodeOperator {
+ t.Helper()
+
nops := make([]capabilities_registry.CapabilitiesRegistryNodeOperator, 0)
- for nop := range req.NopToNodes {
+ for nop := range nop2Nodes {
nops = append(nops, nop)
}
+
sort.Slice(nops, func(i, j int) bool {
return nops[i].Name < nops[j].Name
})
- addNopsResp := addNops(t, lggr, chain, registry, nops)
- require.Len(t, addNopsResp.Nops, len(nops))
+ return nops
+}
- // add capabilities to registry
- capCache := NewCapabiltyCache(t)
+// MustAddCapabilities adds the capabilities to the registry and returns the registered capabilities
+// if the capability is already registered, this call will fail.
+func MustAddCapabilities(
+ t *testing.T,
+ lggr logger.Logger,
+ in map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability,
+ chain deployment.Chain,
+ registry *capabilities_registry.CapabilitiesRegistry,
+) ([]internal.RegisteredCapability, *CapabilityCache) {
+ t.Helper()
+ cache := NewCapabiltyCache(t)
var capabilities []capabilities_registry.CapabilitiesRegistryCapability
- for _, caps := range req.P2pToCapabilities {
+ for _, caps := range in {
capabilities = append(capabilities, caps...)
}
- registeredCapabilities := capCache.AddCapabilities(lggr, chain, registry, capabilities)
+
+ registeredCapabilities := cache.AddCapabilities(lggr, chain, registry, capabilities)
expectedDeduped := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{})
for _, cap := range capabilities {
expectedDeduped[cap] = struct{}{}
}
require.Len(t, registeredCapabilities, len(expectedDeduped))
+ return registeredCapabilities, cache
+}
- // make the nodes and register node
- var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams
- initialp2pToCapabilities := make(map[p2pkey.PeerID][][32]byte)
- for p2pID := range req.P2pToCapabilities {
- initialp2pToCapabilities[p2pID] = mustCapabilityIds(t, registry, registeredCapabilities)
+// GetRegisteredCapabilities returns the registered capabilities for the given capabilities. Each
+// capability must exist on the cache already.
+func GetRegisteredCapabilities(
+ t *testing.T,
+ lggr logger.Logger,
+ in map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability,
+ cache *CapabilityCache,
+) []internal.RegisteredCapability {
+ t.Helper()
+
+ var capabilities []capabilities_registry.CapabilitiesRegistryCapability
+ for _, caps := range in {
+ capabilities = append(capabilities, caps...)
}
- // create node with initial capabilities assigned to nop
- for i, nop := range nops {
- if _, exists := req.NopToNodes[nop]; !exists {
- require.Fail(t, "missing nopToNodes for %s", nop.Name)
- }
- for _, p2pSignerEnc := range req.NopToNodes[nop] {
- nodeParams = append(nodeParams, capabilities_registry.CapabilitiesRegistryNodeParams{
- Signer: p2pSignerEnc.Signer,
- P2pId: p2pSignerEnc.P2PKey,
- EncryptionPublicKey: p2pSignerEnc.EncryptionPublicKey,
- HashedCapabilityIds: initialp2pToCapabilities[p2pSignerEnc.P2PKey],
- NodeOperatorId: uint32(i + 1), // nopid in contract is 1-indexed
- })
- }
+
+ registeredCapabilities := make([]internal.RegisteredCapability, 0)
+ for _, cap := range capabilities {
+ id, exists := cache.Get(cap)
+ require.True(t, exists, "capability not found in cache %v", cap)
+ registeredCapabilities = append(registeredCapabilities, internal.RegisteredCapability{
+ CapabilitiesRegistryCapability: cap,
+ ID: id,
+ })
}
- addNodes(t, lggr, chain, registry, nodeParams)
- // add the Dons
- addDons(t, lggr, chain, registry, capCache, req.Dons)
+ return registeredCapabilities
+}
- return &SetupTestRegistryResponse{
- Registry: registry,
- Chain: chain,
- RegistrySelector: chain.Selector,
- ContractSet: &internal.ContractSet{
- CapabilitiesRegistry: registry,
- },
+func ToP2PToCapabilities(
+ t *testing.T,
+ in map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability,
+ registry *capabilities_registry.CapabilitiesRegistry,
+ caps []internal.RegisteredCapability,
+) map[p2pkey.PeerID][][32]byte {
+ t.Helper()
+ out := make(map[p2pkey.PeerID][][32]byte)
+ for p2pID := range in {
+ out[p2pID] = mustCapabilityIds(t, registry, caps)
}
+ return out
}
func deployCapReg(t *testing.T, chain deployment.Chain) *capabilities_registry.CapabilitiesRegistry {
@@ -139,7 +242,13 @@ func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry
return resp
}
-func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nodes []capabilities_registry.CapabilitiesRegistryNodeParams) {
+func AddNodes(
+ t *testing.T,
+ lggr logger.Logger,
+ chain deployment.Chain,
+ registry *capabilities_registry.CapabilitiesRegistry,
+ nodes []capabilities_registry.CapabilitiesRegistryNodeParams,
+) {
tx, err := registry.AddNodes(chain.DeployerKey, nodes)
if err != nil {
err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)
@@ -149,7 +258,14 @@ func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry
require.NoError(t, err)
}
-func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don) {
+func addDons(
+ t *testing.T,
+ _ logger.Logger,
+ chain deployment.Chain,
+ registry *capabilities_registry.CapabilitiesRegistry,
+ capCache *CapabilityCache,
+ dons []Don,
+) {
for _, don := range dons {
acceptsWorkflows := false
// lookup the capabilities
diff --git a/deployment/keystone/changeset/update_don.go b/deployment/keystone/changeset/update_don.go
index 47cb7c82507..6f168bb55d6 100644
--- a/deployment/keystone/changeset/update_don.go
+++ b/deployment/keystone/changeset/update_don.go
@@ -108,10 +108,10 @@ func updateDonRequest(env deployment.Environment, r *UpdateDonRequest) (*interna
contractSet := resp.ContractSets[r.RegistryChainSel]
return &internal.UpdateDonRequest{
- Chain: env.Chains[r.RegistryChainSel],
- ContractSet: &contractSet,
- P2PIDs: r.P2PIDs,
- CapabilityConfigs: r.CapabilityConfigs,
- UseMCMS: r.UseMCMS(),
+ Chain: env.Chains[r.RegistryChainSel],
+ CapabilitiesRegistry: contractSet.CapabilitiesRegistry,
+ P2PIDs: r.P2PIDs,
+ CapabilityConfigs: r.CapabilityConfigs,
+ UseMCMS: r.UseMCMS(),
}, nil
}
diff --git a/deployment/keystone/changeset/update_don_test.go b/deployment/keystone/changeset/update_don_test.go
index 3fadb7822e2..501afb77e21 100644
--- a/deployment/keystone/changeset/update_don_test.go
+++ b/deployment/keystone/changeset/update_don_test.go
@@ -11,7 +11,7 @@ import (
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal"
- internaltest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test"
+
"github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test"
kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey"
@@ -31,10 +31,10 @@ func TestUpdateDon(t *testing.T) {
}
caps = []kcr.CapabilitiesRegistryCapability{capA, capB}
)
- capACfg := internaltest.GetDefaultCapConfig(t, capA)
+ capACfg := test.GetDefaultCapConfig(t, capA)
capACfgB, err := proto.Marshal(capACfg)
require.NoError(t, err)
- capBCfg := internaltest.GetDefaultCapConfig(t, capB)
+ capBCfg := test.GetDefaultCapConfig(t, capB)
capBCfgB, err := proto.Marshal(capBCfg)
require.NoError(t, err)
diff --git a/deployment/keystone/changeset/update_node_capabilities.go b/deployment/keystone/changeset/update_node_capabilities.go
index c96393328db..bf869416604 100644
--- a/deployment/keystone/changeset/update_node_capabilities.go
+++ b/deployment/keystone/changeset/update_node_capabilities.go
@@ -61,15 +61,19 @@ type MutateNodeCapabilitiesRequest struct {
MCMSConfig *MCMSConfig
}
-func (req *MutateNodeCapabilitiesRequest) Validate() error {
+func (req *MutateNodeCapabilitiesRequest) Validate(e deployment.Environment) error {
if len(req.P2pToCapabilities) == 0 {
return errors.New("p2pToCapabilities is empty")
}
_, exists := chainsel.ChainBySelector(req.RegistryChainSel)
if !exists {
- return fmt.Errorf("registry chain selector %d does not exist", req.RegistryChainSel)
+ return fmt.Errorf("invalid registry chain selector %d: selector does not exist", req.RegistryChainSel)
}
+ _, exists = e.Chains[req.RegistryChainSel]
+ if !exists {
+ return fmt.Errorf("invalid registry chain selector %d: chain does not exist in environment", req.RegistryChainSel)
+ }
return nil
}
@@ -77,37 +81,34 @@ func (req *MutateNodeCapabilitiesRequest) UseMCMS() bool {
return req.MCMSConfig != nil
}
-func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e deployment.Environment) (*internal.UpdateNodeCapabilitiesImplRequest, error) {
- if err := req.Validate(); err != nil {
- return nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err)
- }
- registryChain, ok := e.Chains[req.RegistryChainSel]
- if !ok {
- return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel)
+func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e deployment.Environment) (*internal.UpdateNodeCapabilitiesImplRequest, *ContractSet, error) {
+ if err := req.Validate(e); err != nil {
+ return nil, nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err)
}
+ registryChain := e.Chains[req.RegistryChainSel] // exists because of the validation above
resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{
Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain},
AddressBook: e.ExistingAddresses,
})
if err != nil {
- return nil, fmt.Errorf("failed to get contract sets: %w", err)
+ return nil, nil, fmt.Errorf("failed to get contract sets: %w", err)
}
contractSet, exists := resp.ContractSets[req.RegistryChainSel]
if !exists {
- return nil, fmt.Errorf("contract set not found for chain %d", req.RegistryChainSel)
+ return nil, nil, fmt.Errorf("contract set not found for chain %d", req.RegistryChainSel)
}
return &internal.UpdateNodeCapabilitiesImplRequest{
- Chain: registryChain,
- ContractSet: &contractSet,
- P2pToCapabilities: req.P2pToCapabilities,
- UseMCMS: req.UseMCMS(),
- }, nil
+ Chain: registryChain,
+ CapabilitiesRegistry: contractSet.CapabilitiesRegistry,
+ P2pToCapabilities: req.P2pToCapabilities,
+ UseMCMS: req.UseMCMS(),
+ }, &contractSet, nil
}
// UpdateNodeCapabilities updates the capabilities of nodes in the registry
func UpdateNodeCapabilities(env deployment.Environment, req *UpdateNodeCapabilitiesRequest) (deployment.ChangesetOutput, error) {
- c, err := req.updateNodeCapabilitiesImplRequest(env)
+ c, contractSet, err := req.updateNodeCapabilitiesImplRequest(env)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to convert request: %w", err)
}
@@ -123,10 +124,10 @@ func UpdateNodeCapabilities(env deployment.Environment, req *UpdateNodeCapabilit
return out, errors.New("expected MCMS operation to be non-nil")
}
timelocksPerChain := map[uint64]common.Address{
- c.Chain.Selector: c.ContractSet.Timelock.Address(),
+ c.Chain.Selector: contractSet.Timelock.Address(),
}
proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{
- c.Chain.Selector: c.ContractSet.ProposerMcm,
+ c.Chain.Selector: contractSet.ProposerMcm,
}
proposal, err := proposalutils.BuildProposalFromBatches(
diff --git a/deployment/keystone/changeset/update_nodes.go b/deployment/keystone/changeset/update_nodes.go
index 4a98f8b06e9..cc7c1c08eb7 100644
--- a/deployment/keystone/changeset/update_nodes.go
+++ b/deployment/keystone/changeset/update_nodes.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers"
"github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock"
+ chainsel "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
@@ -30,10 +31,21 @@ type UpdateNodesRequest struct {
MCMSConfig *MCMSConfig
}
-func (r *UpdateNodesRequest) Validate() error {
+func (r *UpdateNodesRequest) Validate(e deployment.Environment) error {
if r.P2pToUpdates == nil {
return errors.New("P2pToUpdates must be non-nil")
}
+
+ _, exists := chainsel.ChainBySelector(r.RegistryChainSel)
+ if !exists {
+ return fmt.Errorf("invalid registry chain selector %d: selector does not exist", r.RegistryChainSel)
+ }
+
+ _, exists = e.Chains[r.RegistryChainSel]
+ if !exists {
+ return fmt.Errorf("invalid registry chain selector %d: chain does not exist in environment", r.RegistryChainSel)
+ }
+
return nil
}
@@ -64,10 +76,10 @@ func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (deploymen
}
resp, err := internal.UpdateNodes(env.Logger, &internal.UpdateNodesRequest{
- Chain: registryChain,
- ContractSet: &contracts,
- P2pToUpdates: req.P2pToUpdates,
- UseMCMS: req.UseMCMS(),
+ Chain: registryChain,
+ CapabilitiesRegistry: contracts.CapabilitiesRegistry,
+ P2pToUpdates: req.P2pToUpdates,
+ UseMCMS: req.UseMCMS(),
})
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to update don: %w", err)
diff --git a/deployment/keystone/deprecated.go b/deployment/keystone/deprecated.go
deleted file mode 100644
index 71a462384e4..00000000000
--- a/deployment/keystone/deprecated.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package keystone
-
-import "github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
-
-//TODO: delete this after the downstream migration is done
-
-// Deprecated: Use changeset package instead
-// OracleConfig is the configuration for an oracle
-type OracleConfig = changeset.OracleConfig
-
-// Deprecated: Use changeset package instead
-// OCR3OnchainConfig is the onchain configuration of an OCR2 contract
-type OCR2OracleConfig = changeset.OCR3OnchainConfig
-
-// Deprecated: Use changeset package instead
-// NodeKeys is a set of public keys for a node
-type NodeKeys = changeset.NodeKeys
-
-// Deprecated: Use changeset package instead
-// TopLevelConfigSource is the top level configuration source
-type TopLevelConfigSource = changeset.TopLevelConfigSource
-
-// Deprecated: Use changeset package instead
-// GenerateOCR3Config generates an OCR3 config
-var GenerateOCR3Config = changeset.GenerateOCR3Config
-
-// Deprecated: Use changeset package instead
-// FeedConsumer is a feed consumer contract type
-var FeedConsumer = changeset.FeedConsumer
-
-// Deprecated: Use changeset package instead
-// KeystoneForwarder is a keystone forwarder contract type
-var KeystoneForwarder = changeset.KeystoneForwarder
-
-// Deprecated: Use changeset package instead
-// GetContractSetsRequest is a request to get contract sets
-type GetContractSetsRequest = changeset.GetContractSetsRequest
-
-// Deprecated: Use changeset package instead
-// GetContractSetsResponse is a response to get contract sets
-type GetContractSetsResponse = changeset.GetContractSetsResponse
-
-// Deprecated: Use changeset package instead
-// GetContractSets gets contract sets
-var GetContractSets = changeset.GetContractSets
-
-// Deprecated: Use changeset package instead
-// RegisterCapabilitiesRequest is a request to register capabilities
-type RegisterCapabilitiesRequest = changeset.RegisterCapabilitiesRequest
-
-// Deprecated: Use changeset package instead
-// RegisterCapabilitiesResponse is a response to register capabilities
-type RegisterCapabilitiesResponse = changeset.RegisterCapabilitiesResponse
-
-// Deprecated: Use changeset package instead
-// RegisterCapabilities registers capabilities
-var RegisterCapabilities = changeset.RegisterCapabilities
-
-// Deprecated: Use changeset package instead
-// RegisterNOPSRequest is a request to register NOPS
-type RegisterNOPSRequest = changeset.RegisterNOPSRequest
-
-// Deprecated: Use changeset package instead
-// RegisterNOPSResponse is a response to register NOPS
-type RegisterNOPSResponse = changeset.RegisterNOPSResponse
-
-// Deprecated: Use changeset package instead
-// RegisterNOPS registers NOPS
-var RegisterNOPS = changeset.RegisterNOPS
-
-// Deprecated: Use changeset package instead
-// RegisterNodesRequest is a request to register nodes with the capabilities registry
-type RegisterNodesRequest = changeset.RegisterNodesRequest
-
-// Deprecated: Use changeset package instead
-// RegisterNodesResponse is a response to register nodes with the capabilities registry
-type RegisterNodesResponse = changeset.RegisterNodesResponse
-
-// Deprecated: Use changeset package instead
-// RegisterNodes registers nodes with the capabilities registry
-var RegisterNodes = changeset.RegisterNodes
-
-// Deprecated: Use changeset package instead
-// RegisteredCapability is a wrapper of a capability and its ID
-type RegisteredCapability = changeset.RegisteredCapability
-
-// Deprecated: Use changeset package instead
-// FromCapabilitiesRegistryCapability converts a capabilities registry capability to a registered capability
-var FromCapabilitiesRegistryCapability = changeset.FromCapabilitiesRegistryCapability
-
-// Deprecated: Use changeset package instead
-// RegisterDonsRequest is a request to register Dons with the capabilities registry
-type RegisterDonsRequest = changeset.RegisterDonsRequest
-
-// Deprecated: Use changeset package instead
-// RegisterDonsResponse is a response to register Dons with the capabilities registry
-type RegisterDonsResponse = changeset.RegisterDonsResponse
-
-// Deprecated: Use changeset package instead
-// RegisterDons registers Dons with the capabilities registry
-var RegisterDons = changeset.RegisterDons
-
-// Deprecated: Use changeset package instead
-// DONToRegister is the minimal information needed to register a DON with the capabilities registry
-type DONToRegister = changeset.DONToRegister
-
-// Deprecated: Use changeset package instead
-// ConfigureContractsRequest is a request to configure ALL the contracts
-type ConfigureContractsRequest = changeset.ConfigureContractsRequest
-
-// Deprecated: Use changeset package instead
-// ConfigureContractsResponse is a response to configure ALL the contracts
-type ConfigureContractsResponse = changeset.ConfigureContractsResponse
-
-// Deprecated: Use changeset package instead
-// DonCapabilities is a set of capabilities hosted by a set of node operators
-// in is in a convenient form to handle the CLO representation of the nop data
-type DonCapabilities = changeset.DonCapabilities
-
-// Deprecated: Use changeset package instead
-type DeployRequest = changeset.DeployRequest
-
-// Deprecated: Use changeset package instead
-type DeployResponse = changeset.DeployResponse
-
-// Deprecated: Use changeset package instead
-type ContractSet = changeset.ContractSet
diff --git a/deployment/solana_chain.go b/deployment/solana_chain.go
index 5dd6e0918f6..1bc643924be 100644
--- a/deployment/solana_chain.go
+++ b/deployment/solana_chain.go
@@ -2,6 +2,7 @@ package deployment
import (
"bytes"
+ "context"
"fmt"
"os"
"os/exec"
@@ -14,10 +15,21 @@ import (
solRpc "github.com/gagliardetto/solana-go/rpc"
"github.com/pkg/errors"
- solCommomUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
+ solBinary "github.com/gagliardetto/binary"
+ "github.com/gagliardetto/solana-go/rpc"
+
+ solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
)
+var (
+ SolDefaultCommitment = rpc.CommitmentConfirmed
+ SolDefaultGasLimit = solBinary.Uint128{Lo: 3000, Hi: 0, Endianness: nil}
+ SolDefaultMaxFeeJuelsPerMsg = solBinary.Uint128{Lo: 300000000, Hi: 0, Endianness: nil}
+ SPL2022Tokens = "SPL2022Tokens"
+ SPLTokens = "SPLTokens"
+)
+
// SolChain represents a Solana chain.
type SolChain struct {
// Selectors used as canonical chain identifier.
@@ -28,7 +40,7 @@ type SolChain struct {
WSURL string
// TODO: raw private key for now, need to replace with a more secure way
DeployerKey *solana.PrivateKey
- Confirm func(instructions []solana.Instruction, opts ...solCommomUtil.TxModifier) error
+ Confirm func(instructions []solana.Instruction, opts ...solCommonUtil.TxModifier) error
// deploy uses the solana CLI which needs a keyfile
KeypairPath string
@@ -56,15 +68,7 @@ func (c SolChain) Name() string {
return chainInfo.ChainName
}
-var allowedPrograms = map[string]bool{
- "ccip_router": true,
- // Add other valid program names here
-}
-
func (c SolChain) DeployProgram(logger logger.Logger, programName string) (string, error) {
- if !allowedPrograms[programName] {
- return "", fmt.Errorf("program %s not in allowed list", programName)
- }
programFile := filepath.Join(c.ProgramsPath, programName+".so")
if _, err := os.Stat(programFile); err != nil {
return "", fmt.Errorf("program file not found: %w", err)
@@ -111,6 +115,14 @@ func (c SolChain) DeployProgram(logger logger.Logger, programName string) (strin
return parseProgramID(output)
}
+func (c SolChain) GetAccountDataBorshInto(ctx context.Context, pubkey solana.PublicKey, accountState interface{}) error {
+ err := solCommonUtil.GetAccountDataBorshInto(ctx, c.Client, pubkey, SolDefaultCommitment, accountState)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
// parseProgramID parses the program ID from the deploy output.
func parseProgramID(output string) (string, error) {
// Look for the program ID in the CLI output
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index fa58a3c2dcd..2bc61cd64aa 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -2989,9 +2989,9 @@ Enabled = true
[GasEstimator]
Mode = 'BlockHistory'
-PriceDefault = '5 gwei'
+PriceDefault = '1 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
-PriceMin = '3 gwei'
+PriceMin = '1 gwei'
LimitDefault = 500000
LimitMax = 500000
LimitMultiplier = '1'
@@ -3275,6 +3275,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 100
FinalityTagEnabled = true
+LinkContractAddress = '0xe74037112db8807B3B4B3895F5790e5bc1866a29'
LogBackfillBatchSize = 1000
LogPollInterval = '6s'
LogKeepBlocksDepth = 100000
@@ -3418,7 +3419,7 @@ Enabled = true
[GasEstimator]
Mode = 'BlockHistory'
-PriceDefault = '5 gwei'
+PriceDefault = '1 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 gwei'
LimitDefault = 500000
@@ -3816,6 +3817,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x8418c4d7e8e17ab90232DC72150730E6c4b84F57'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -4035,6 +4037,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
LogBackfillBatchSize = 1000
LogPollInterval = '1s'
LogKeepBlocksDepth = 100000
@@ -4251,6 +4254,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -4363,6 +4367,7 @@ BlockBackfillSkip = false
ChainType = 'xlayer'
FinalityDepth = 500
FinalityTagEnabled = false
+LinkContractAddress = '0x724593f6FCb0De4E6902d4C55D7C74DaA2AF0E55'
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
@@ -4472,6 +4477,7 @@ BlockBackfillSkip = false
ChainType = 'xlayer'
FinalityDepth = 500
FinalityTagEnabled = false
+LinkContractAddress = '0x8aF9711B44695a5A081F25AB9903DDB73aCf8FA9'
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
@@ -4581,6 +4587,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 2000
FinalityTagEnabled = true
+LinkContractAddress = '0x709229D9587886a1eDFeE6b5cE636E1D70d1cE39'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -4801,6 +4808,7 @@ BlockBackfillSkip = false
ChainType = 'kroma'
FinalityDepth = 400
FinalityTagEnabled = true
+LinkContractAddress = '0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -4904,7 +4912,7 @@ GasLimitDefault = 400000
-zkSync Goerli (280)
+ZKsync Goerli (280)
```toml
AutoCreateKey = true
@@ -4913,6 +4921,7 @@ BlockBackfillSkip = false
ChainType = 'zksync'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0xD29F4Cc763A064b6C563B8816f09351b3Fbb61A0'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -5024,6 +5033,7 @@ BlockBackfillSkip = false
ChainType = 'hedera'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x7Ce6bb2Cc2D3Fd45a974Da6a0F29236cb9513a98'
LogBackfillBatchSize = 1000
LogPollInterval = '10s'
LogKeepBlocksDepth = 100000
@@ -5132,6 +5142,7 @@ BlockBackfillSkip = false
ChainType = 'hedera'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x90a386d59b9A6a4795a011e8f032Fc21ED6FEFb6'
LogBackfillBatchSize = 1000
LogPollInterval = '10s'
LogKeepBlocksDepth = 100000
@@ -5231,7 +5242,7 @@ GasLimitDefault = 400000
-zkSync Sepolia (300)
+ZKsync Sepolia (300)
```toml
AutoCreateKey = true
@@ -5240,6 +5251,7 @@ BlockBackfillSkip = false
ChainType = 'zksync'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x23A1aFD896c8c8876AF46aDc38521f4432658d1e'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -5342,7 +5354,7 @@ GasLimitDefault = 400000
-zkSync Mainnet (324)
+ZKsync Mainnet (324)
```toml
AutoCreateKey = true
@@ -5351,6 +5363,7 @@ BlockBackfillSkip = false
ChainType = 'zksync'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x52869bae3E091e36b0915941577F2D47d8d8B534'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -5575,6 +5588,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 2500
FinalityTagEnabled = true
+LinkContractAddress = '0x915b648e994d5f31059B38223b9fbe98ae185473'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -5795,6 +5809,7 @@ BlockBackfillSkip = false
ChainType = 'astar'
FinalityDepth = 100
FinalityTagEnabled = true
+LinkContractAddress = '0x31EFB841d5e0b4082F7E1267dab8De1b853f2A9d'
LogBackfillBatchSize = 1000
LogPollInterval = '6s'
LogKeepBlocksDepth = 100000
@@ -5903,6 +5918,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x925a4bfE64AE2bFAC8a02b35F78e60C29743755d'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -6122,6 +6138,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0xd2FE54D1E5F568eB710ba9d898Bf4bD02C7c0353'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -6230,6 +6247,7 @@ BlockBackfillSkip = false
ChainType = 'zkevm'
FinalityDepth = 500
FinalityTagEnabled = false
+LinkContractAddress = '0xdB7A504CF869484dd6aC5FaF925c8386CBF7573D'
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
@@ -6339,6 +6357,7 @@ BlockBackfillSkip = false
ChainType = 'wemix'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x80f1FcdC96B55e459BF52b998aBBE2c364935d69'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -6447,6 +6466,7 @@ BlockBackfillSkip = false
ChainType = 'wemix'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x3580c7A817cCD41f7e02143BFa411D4EeAE78093'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -6554,6 +6574,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 7
FinalityTagEnabled = false
+LinkContractAddress = '0x6C475841d1D7871940E93579E5DBaE01634e17aA'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -6769,6 +6790,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 2000
FinalityTagEnabled = true
+LinkContractAddress = '0x436a1907D9e6a65E6db73015F08f9C66F6B63E45'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -6881,6 +6903,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 2000
FinalityTagEnabled = true
+LinkContractAddress = '0xda40816f278Cd049c137F6612822D181065EBfB4'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -7100,7 +7123,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
-LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2'
+LinkContractAddress = '0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -7542,6 +7565,7 @@ BlockBackfillSkip = false
ChainType = 'kroma'
FinalityDepth = 400
FinalityTagEnabled = true
+LinkContractAddress = '0xa75cCA5b404ec6F4BB6EC4853D177FE7057085c8'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -7654,6 +7678,7 @@ BlockBackfillSkip = false
ChainType = 'zkevm'
FinalityDepth = 500
FinalityTagEnabled = false
+LinkContractAddress = '0x5576815a38A3706f37bf815b261cCc7cCA77e975'
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
@@ -7762,6 +7787,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x7311DED199CC28D80E58e81e8589aa160199FCD2'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -7978,6 +8004,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 2500
FinalityTagEnabled = true
+LinkContractAddress = '0xC82Ea35634BcE95C394B6BC00626f827bB0F4801'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -8090,6 +8117,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 1200
FinalityTagEnabled = true
+LinkContractAddress = '0xfe36cF0B43aAe49fBc5cFC5c0AF22a623114E043'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -8203,6 +8231,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 1200
FinalityTagEnabled = true
+LinkContractAddress = '0x22bdEdEa0beBdD7CfFC95bA53826E55afFE9DE04'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -8423,6 +8452,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -8642,6 +8672,7 @@ BlockBackfillSkip = false
ChainType = 'gnosis'
FinalityDepth = 100
FinalityTagEnabled = false
+LinkContractAddress = '0xDCA67FD8324990792C0bfaE95903B8A64097754F'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -8973,6 +9004,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x685cE6742351ae9b618F383883D6d1e0c5A31B4B'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -9081,6 +9113,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x183E3691EfF3524B2315D3703D94F922CbE51F54'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -9193,6 +9226,7 @@ BlockBackfillSkip = false
ChainType = 'zksync'
FinalityDepth = 40
FinalityTagEnabled = false
+LinkContractAddress = '0x7f1b9eE544f9ff9bB521Ab79c205d79C55250a36'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -9416,6 +9450,7 @@ BlockBackfillSkip = false
ChainType = 'celo'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0xd07294e6E917e07dfDcee882dd1e2565085C2ae0'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -9740,6 +9775,7 @@ BlockBackfillSkip = false
ChainType = 'celo'
FinalityDepth = 2750
FinalityTagEnabled = true
+LinkContractAddress = '0x32E08557B14FaD8908025619797221281D439071'
LogBackfillBatchSize = 1000
LogPollInterval = '1s'
LogKeepBlocksDepth = 100000
@@ -10077,6 +10113,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x61876F0429726D7777B46f663e1C9ab75d08Fc56'
LogBackfillBatchSize = 1000
LogPollInterval = '1s'
LogKeepBlocksDepth = 100000
@@ -10185,6 +10222,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 3000
FinalityTagEnabled = true
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -10403,6 +10441,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 900
FinalityTagEnabled = false
+LinkContractAddress = '0xF64E6E064a71B45514691D397ad4204972cD6508'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -10512,6 +10551,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 300
FinalityTagEnabled = false
+LinkContractAddress = '0xa18152629128738a5c081eb226335FEd4B9C95e9'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -10622,6 +10662,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x9870D6a0e05F867EAAe696e106741843F7fD116D'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -10730,6 +10771,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 3150
FinalityTagEnabled = true
+LinkContractAddress = '0x5aB885CDa7216b163fb6F813DEC1E1532516c833'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -10949,6 +10991,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 500
FinalityTagEnabled = false
+LinkContractAddress = '0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904'
LogBackfillBatchSize = 1000
LogPollInterval = '1s'
LogKeepBlocksDepth = 100000
@@ -11056,6 +11099,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x52CEEed7d3f8c6618e4aaD6c6e555320d0D83271'
LogBackfillBatchSize = 1000
LogPollInterval = '6s'
LogKeepBlocksDepth = 100000
@@ -11164,6 +11208,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x93202eC683288a9EA75BB829c6baCFb2BfeA9013'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -11388,6 +11433,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -11499,6 +11545,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 21
FinalityTagEnabled = false
+LinkContractAddress = '0x2A5bACb2440BC17D53B7b9Be73512dDf92265e48'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -11606,6 +11653,7 @@ BlockBackfillDepth = 10
BlockBackfillSkip = false
FinalityDepth = 21
FinalityTagEnabled = false
+LinkContractAddress = '0x56B275c0Ec034a229a1deD8DB17089544bc276D9'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -11938,6 +11986,7 @@ BlockBackfillSkip = false
ChainType = 'arbitrum'
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0xb1D4538B4571d411F07960EF2838Ce337FE1E80E'
LogBackfillBatchSize = 1000
LogPollInterval = '1s'
LogKeepBlocksDepth = 100000
@@ -12049,6 +12098,7 @@ BlockBackfillSkip = false
ChainType = 'scroll'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x231d45b53C905c3d6201318156BDC725c9c3B9B1'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -12162,6 +12212,7 @@ BlockBackfillSkip = false
ChainType = 'scroll'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x548C6944cba02B9D1C0570102c89de64D258d3Ac'
LogBackfillBatchSize = 1000
LogPollInterval = '5s'
LogKeepBlocksDepth = 100000
@@ -12275,6 +12326,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 3000
FinalityTagEnabled = true
+LinkContractAddress = '0x3423C922911956b1Ccbc2b5d4f38216a6f4299b4'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -12387,6 +12439,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 3150
FinalityTagEnabled = true
+LinkContractAddress = '0xcd2AfB2933391E35e8682cbaaF75d9CA7339b183'
LogBackfillBatchSize = 1000
LogPollInterval = '3s'
LogKeepBlocksDepth = 100000
@@ -12607,6 +12660,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
@@ -12719,6 +12773,7 @@ BlockBackfillSkip = false
ChainType = 'arbitrum'
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x7311DED199CC28D80E58e81e8589aa160199FCD2'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -12830,6 +12885,7 @@ BlockBackfillSkip = false
ChainType = 'arbitrum'
FinalityDepth = 50
FinalityTagEnabled = true
+LinkContractAddress = '0x996EfAb6011896Be832969D91E9bc1b3983cfdA1'
LogBackfillBatchSize = 1000
LogPollInterval = '15s'
LogKeepBlocksDepth = 100000
@@ -12941,6 +12997,7 @@ BlockBackfillSkip = false
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x02c359ebf98fc8BF793F970F9B8302bb373BdF32'
LogBackfillBatchSize = 1000
LogPollInterval = '2s'
LogKeepBlocksDepth = 100000
diff --git a/evm/README.md b/evm/README.md
index 75fe0b42279..59e57caed51 100644
--- a/evm/README.md
+++ b/evm/README.md
@@ -1,4 +1,4 @@
# chainlink/evm
This directory tree is a temporary location for code being extracted to another module, in another repo.
-Packages in this tree must not import packages outside of this tree.
+Packages in this tree must not import packages outside of this tree (except for `core/gethwrappers/`).
diff --git a/evm/client/clienttest/clienttest.go b/evm/client/clienttest/clienttest.go
index fc774d287e6..6a67b4b20a8 100644
--- a/evm/client/clienttest/clienttest.go
+++ b/evm/client/clienttest/clienttest.go
@@ -18,7 +18,6 @@ func NewClientWithDefaultChainID(t *testing.T) *Client {
return c
}
-// TODO move to clienttest?
type MockEth struct {
EthClient *Client
CheckFilterLogs func(int64, int64)
diff --git a/evm/config/chain_scoped.go b/evm/config/chain_scoped.go
index eb29a49d012..37d8faa43f4 100644
--- a/evm/config/chain_scoped.go
+++ b/evm/config/chain_scoped.go
@@ -5,22 +5,16 @@ import (
"time"
"github.com/smartcontractkit/chainlink-common/pkg/assets"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
-
"github.com/smartcontractkit/chainlink/v2/evm/config/chaintype"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
)
-func NewTOMLChainScopedConfig(tomlConfig *toml.EVMConfig, lggr logger.Logger) *ChainScoped {
- return &ChainScoped{
- evmConfig: &EVMConfig{C: tomlConfig},
- lggr: lggr}
+func NewTOMLChainScopedConfig(tomlConfig *toml.EVMConfig) *ChainScoped {
+ return &ChainScoped{evmConfig: &EVMConfig{C: tomlConfig}}
}
-// ChainScoped implements config.ChainScopedConfig with a gencfg.BasicConfig and EVMConfig.
+// ChainScoped implements config.ChainScopedConfig with EVMConfig.
type ChainScoped struct {
- lggr logger.Logger
-
evmConfig *EVMConfig
}
diff --git a/evm/config/configtest/configtest.go b/evm/config/configtest/configtest.go
index facefec5548..9092b81c001 100644
--- a/evm/config/configtest/configtest.go
+++ b/evm/config/configtest/configtest.go
@@ -3,13 +3,12 @@ package configtest
import (
"testing"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/v2/evm/config"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/utils/big"
)
-func NewChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig)) config.ChainScopedConfig {
+func NewChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig)) *config.ChainScoped {
chainID := big.NewI(0)
evmCfg := &toml.EVMConfig{
ChainID: chainID,
@@ -24,5 +23,5 @@ func NewChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig)) conf
overrideFn(evmCfg)
}
- return config.NewTOMLChainScopedConfig(evmCfg, logger.Test(t))
+ return config.NewTOMLChainScopedConfig(evmCfg)
}
diff --git a/evm/config/toml/config.go b/evm/config/toml/config.go
index 64fe11372d6..ff41176c853 100644
--- a/evm/config/toml/config.go
+++ b/evm/config/toml/config.go
@@ -163,6 +163,17 @@ func (cs EVMConfigs) NodeStatus(name string) (commontypes.NodeStatus, error) {
return commontypes.NodeStatus{}, fmt.Errorf("node %s: %w", name, ErrNotFound)
}
+func (cs EVMConfigs) RPCEnabled() bool {
+ for _, c := range cs {
+ if c.IsEnabled() {
+ if len(c.Nodes) > 0 {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func legacyNode(n *Node, chainID *big.Big) (v2 types.Node) {
v2.Name = *n.Name
v2.EVMChainID = *chainID
diff --git a/evm/config/toml/defaults/Arbitrum_Mainnet.toml b/evm/config/toml/defaults/Arbitrum_Mainnet.toml
index b81d53731fb..9d8a4dc5d74 100644
--- a/evm/config/toml/defaults/Arbitrum_Mainnet.toml
+++ b/evm/config/toml/defaults/Arbitrum_Mainnet.toml
@@ -2,7 +2,7 @@
ChainID = '42161'
ChainType = 'arbitrum'
FinalityTagEnabled = true
-LinkContractAddress = "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4"
+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'
diff --git a/evm/config/toml/defaults/Arbitrum_Rinkeby.toml b/evm/config/toml/defaults/Arbitrum_Rinkeby.toml
index 68e28e7c5bc..736cba44a6a 100644
--- a/evm/config/toml/defaults/Arbitrum_Rinkeby.toml
+++ b/evm/config/toml/defaults/Arbitrum_Rinkeby.toml
@@ -1,6 +1,6 @@
ChainID = '421611'
ChainType = 'arbitrum'
-LinkContractAddress = "0x615fBe6372676474d9e6933d310469c9b68e9726"
+LinkContractAddress = '0x615fBe6372676474d9e6933d310469c9b68e9726'
LogPollInterval = '1s'
NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
diff --git a/evm/config/toml/defaults/Arbitrum_Sepolia.toml b/evm/config/toml/defaults/Arbitrum_Sepolia.toml
index ab5351b9a74..bcac6443b5f 100644
--- a/evm/config/toml/defaults/Arbitrum_Sepolia.toml
+++ b/evm/config/toml/defaults/Arbitrum_Sepolia.toml
@@ -1,6 +1,7 @@
ChainID = '421614'
ChainType = 'arbitrum'
FinalityTagEnabled = true
+LinkContractAddress = '0xb1D4538B4571d411F07960EF2838Ce337FE1E80E'
NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
LogPollInterval = '1s'
diff --git a/evm/config/toml/defaults/Astar_Mainnet.toml b/evm/config/toml/defaults/Astar_Mainnet.toml
index 12c66b324d6..248a3f83256 100644
--- a/evm/config/toml/defaults/Astar_Mainnet.toml
+++ b/evm/config/toml/defaults/Astar_Mainnet.toml
@@ -2,6 +2,7 @@ ChainID = '592'
ChainType = 'astar'
FinalityTagEnabled = true
FinalityDepth = 100
+LinkContractAddress = '0x31EFB841d5e0b4082F7E1267dab8De1b853f2A9d'
LogPollInterval = '6s'
[GasEstimator]
diff --git a/evm/config/toml/defaults/Astar_Shibuya.toml b/evm/config/toml/defaults/Astar_Shibuya.toml
index cf5298ffe8c..93844521405 100644
--- a/evm/config/toml/defaults/Astar_Shibuya.toml
+++ b/evm/config/toml/defaults/Astar_Shibuya.toml
@@ -1,6 +1,7 @@
ChainID = '81'
FinalityTagEnabled = true
FinalityDepth = 100
+LinkContractAddress = '0xe74037112db8807B3B4B3895F5790e5bc1866a29'
LogPollInterval = '6s'
[GasEstimator]
diff --git a/evm/config/toml/defaults/BOB_Mainnet.toml b/evm/config/toml/defaults/BOB_Mainnet.toml
index 3211ee9caa7..c4c963ba15a 100644
--- a/evm/config/toml/defaults/BOB_Mainnet.toml
+++ b/evm/config/toml/defaults/BOB_Mainnet.toml
@@ -3,6 +3,7 @@ ChainID = '60808'
ChainType = 'optimismBedrock'
# FinalityDepth in mainnet showed more than 3k
FinalityDepth = 3150
+LinkContractAddress = '0x5aB885CDa7216b163fb6F813DEC1E1532516c833'
# block_time was: 2s, adding 1 second buffer
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/BOB_Testnet.toml b/evm/config/toml/defaults/BOB_Testnet.toml
index 064137f97c7..b190221c5bd 100644
--- a/evm/config/toml/defaults/BOB_Testnet.toml
+++ b/evm/config/toml/defaults/BOB_Testnet.toml
@@ -3,6 +3,7 @@ ChainID = '808813'
ChainType = 'optimismBedrock'
# FinalityDepth in mainnet showed more than 3k
FinalityDepth = 3150
+LinkContractAddress = '0xcd2AfB2933391E35e8682cbaaF75d9CA7339b183'
# block_time was: 2s, adding 1 second buffer
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/BSC_Mainnet.toml b/evm/config/toml/defaults/BSC_Mainnet.toml
index 710ef34d309..357bd551998 100644
--- a/evm/config/toml/defaults/BSC_Mainnet.toml
+++ b/evm/config/toml/defaults/BSC_Mainnet.toml
@@ -11,9 +11,7 @@ FinalizedBlockOffset = 2
NoNewFinalizedHeadsThreshold = '45s'
[GasEstimator]
-PriceDefault = '5 gwei'
-# Set to the BSC node's default Eth.Miner.GasPrice config
-PriceMin = '3 gwei'
+PriceDefault = '1 gwei'
# 15s delay since feeds update every minute in volatile situations
BumpThreshold = 5
diff --git a/evm/config/toml/defaults/BSC_Testnet.toml b/evm/config/toml/defaults/BSC_Testnet.toml
index 95eef689d00..f2fc6044b6f 100644
--- a/evm/config/toml/defaults/BSC_Testnet.toml
+++ b/evm/config/toml/defaults/BSC_Testnet.toml
@@ -11,7 +11,7 @@ FinalizedBlockOffset = 2
NoNewFinalizedHeadsThreshold = '40s'
[GasEstimator]
-PriceDefault = '5 gwei'
+PriceDefault = '1 gwei'
# 15s delay since feeds update every minute in volatile situations
BumpThreshold = 5
diff --git a/evm/config/toml/defaults/Base_Mainnet.toml b/evm/config/toml/defaults/Base_Mainnet.toml
index b683aff9840..61bd4b64353 100644
--- a/evm/config/toml/defaults/Base_Mainnet.toml
+++ b/evm/config/toml/defaults/Base_Mainnet.toml
@@ -2,6 +2,7 @@ ChainID = '8453'
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196'
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Base_Sepolia.toml b/evm/config/toml/defaults/Base_Sepolia.toml
index 3e6aee20e29..1c0a72fd450 100644
--- a/evm/config/toml/defaults/Base_Sepolia.toml
+++ b/evm/config/toml/defaults/Base_Sepolia.toml
@@ -2,6 +2,7 @@ ChainID = '84532'
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410'
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Berachain_Testnet.toml b/evm/config/toml/defaults/Berachain_Testnet.toml
index 7024d12a99f..ff0a68b933f 100644
--- a/evm/config/toml/defaults/Berachain_Testnet.toml
+++ b/evm/config/toml/defaults/Berachain_Testnet.toml
@@ -1,8 +1,9 @@
ChainID = '80084'
# finality_depth: instant
-FinalityDepth = 10
+FinalityDepth = 10
+LinkContractAddress = '0x52CEEed7d3f8c6618e4aaD6c6e555320d0D83271'
# block_time: 5s, adding 1 second buffer
-LogPollInterval = '6s'
+LogPollInterval = '6s'
# finality_depth * block_time / 60 secs = ~0.8 min (finality time)
NoNewFinalizedHeadsThreshold = '5m'
diff --git a/evm/config/toml/defaults/Bitlayer_Mainnet.toml b/evm/config/toml/defaults/Bitlayer_Mainnet.toml
index fe2c897ed81..b34fb93aad4 100644
--- a/evm/config/toml/defaults/Bitlayer_Mainnet.toml
+++ b/evm/config/toml/defaults/Bitlayer_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '200901'
FinalityTagEnabled = false
FinalityDepth = 21 # confirmed with Bitlayer team and recommended by docs: https://docs.bitlayer.org/docs/Learn/BitlayerNetwork/AboutFinality/#about-finality-at-stage-bitlayer-pos-bitlayer-mainnet-v1
+LinkContractAddress = '0x56B275c0Ec034a229a1deD8DB17089544bc276D9'
[GasEstimator]
Mode = 'FeeHistory'
diff --git a/evm/config/toml/defaults/Bitlayer_Testnet.toml b/evm/config/toml/defaults/Bitlayer_Testnet.toml
index f0320472503..3cd852d31ef 100644
--- a/evm/config/toml/defaults/Bitlayer_Testnet.toml
+++ b/evm/config/toml/defaults/Bitlayer_Testnet.toml
@@ -1,9 +1,10 @@
ChainID = '200810'
FinalityTagEnabled = false
FinalityDepth = 21 # confirmed with Bitlayer team and recommended by docs: https://docs.bitlayer.org/docs/Learn/BitlayerNetwork/AboutFinality/#about-finality-at-stage-bitlayer-pos-bitlayer-mainnet-v1
+LinkContractAddress = '0x2A5bACb2440BC17D53B7b9Be73512dDf92265e48'
[GasEstimator]
-Mode='FeeHistory'
+Mode = 'FeeHistory'
EIP1559DynamicFees = false
PriceMax = '1 gwei' # DS&A recommended value
PriceMin = '40 mwei' # During testing, we saw minimum gas prices ~50 mwei
diff --git a/evm/config/toml/defaults/Blast_Mainnet.toml b/evm/config/toml/defaults/Blast_Mainnet.toml
index 362edcfc063..65600dc7101 100644
--- a/evm/config/toml/defaults/Blast_Mainnet.toml
+++ b/evm/config/toml/defaults/Blast_Mainnet.toml
@@ -1,7 +1,8 @@
ChainID = '81457'
+ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0x93202eC683288a9EA75BB829c6baCFb2BfeA9013'
# block rate is ~2sec, so this ensures blocks are polled correctly
LogPollInterval = '2s'
diff --git a/evm/config/toml/defaults/Blast_Sepolia.toml b/evm/config/toml/defaults/Blast_Sepolia.toml
index 869c3b2d144..77953a3ac77 100644
--- a/evm/config/toml/defaults/Blast_Sepolia.toml
+++ b/evm/config/toml/defaults/Blast_Sepolia.toml
@@ -1,7 +1,8 @@
ChainID = '168587773'
+ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0x02c359ebf98fc8BF793F970F9B8302bb373BdF32'
# block rate is ~2sec, so this ensures blocks are polled correctly
LogPollInterval = '2s'
diff --git a/evm/config/toml/defaults/Botanix_Testnet.toml b/evm/config/toml/defaults/Botanix_Testnet.toml
index 570f360c878..6459e527112 100644
--- a/evm/config/toml/defaults/Botanix_Testnet.toml
+++ b/evm/config/toml/defaults/Botanix_Testnet.toml
@@ -1,5 +1,6 @@
ChainID = '3636'
FinalityTagEnabled = true
+LinkContractAddress = '0x7311DED199CC28D80E58e81e8589aa160199FCD2'
[GasEstimator]
EIP1559DynamicFees = true
diff --git a/evm/config/toml/defaults/Bsquared_Mainnet.toml b/evm/config/toml/defaults/Bsquared_Mainnet.toml
index 82fb4567771..ce10b9aaf0c 100644
--- a/evm/config/toml/defaults/Bsquared_Mainnet.toml
+++ b/evm/config/toml/defaults/Bsquared_Mainnet.toml
@@ -3,13 +3,14 @@ ChainID = '223'
ChainType = 'optimismBedrock'
# finality_depth was: ~1900
FinalityDepth = 2000
+LinkContractAddress = '0x709229D9587886a1eDFeE6b5cE636E1D70d1cE39'
# block_time: ~2s, adding 1 second buffer
-LogPollInterval = '3s'
+LogPollInterval = '3s'
# finality_depth * block_time / 60 secs = ~66 min (finality time)
-NoNewFinalizedHeadsThreshold = '70m'
+NoNewFinalizedHeadsThreshold = '70m'
-FinalityTagEnabled = true
+FinalityTagEnabled = true
[GasEstimator]
EIP1559DynamicFees = true
diff --git a/evm/config/toml/defaults/Bsquared_Testnet.toml b/evm/config/toml/defaults/Bsquared_Testnet.toml
index 925ef6bea89..ed2b12d7633 100644
--- a/evm/config/toml/defaults/Bsquared_Testnet.toml
+++ b/evm/config/toml/defaults/Bsquared_Testnet.toml
@@ -3,6 +3,7 @@ ChainID = '1123'
ChainType = 'optimismBedrock'
# finality_depth was: ~1900
FinalityDepth = 2000
+LinkContractAddress = '0x436a1907D9e6a65E6db73015F08f9C66F6B63E45'
# block_time: ~2s, adding 1 second buffer
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/Celo_Mainnet.toml b/evm/config/toml/defaults/Celo_Mainnet.toml
index b773f2d19f5..fcbf4a1ca87 100644
--- a/evm/config/toml/defaults/Celo_Mainnet.toml
+++ b/evm/config/toml/defaults/Celo_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '42220'
ChainType = 'celo'
FinalityDepth = 10
+LinkContractAddress = '0xd07294e6E917e07dfDcee882dd1e2565085C2ae0'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '1m'
diff --git a/evm/config/toml/defaults/Celo_Testnet.toml b/evm/config/toml/defaults/Celo_Testnet.toml
index 0e4594150dd..ddb91aaef82 100644
--- a/evm/config/toml/defaults/Celo_Testnet.toml
+++ b/evm/config/toml/defaults/Celo_Testnet.toml
@@ -2,6 +2,7 @@ ChainID = '44787'
ChainType = 'celo'
FinalityTagEnabled = true
FinalityDepth = 2750 # mean finality time of ~37 minutes + 500 block buffer
+LinkContractAddress = '0x32E08557B14FaD8908025619797221281D439071'
LogPollInterval = '1s' # 1 sec block rate
NoNewHeadsThreshold = '1m'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Core_Testnet.toml b/evm/config/toml/defaults/Core_Testnet.toml
index 215d3705bad..c3b77851c49 100644
--- a/evm/config/toml/defaults/Core_Testnet.toml
+++ b/evm/config/toml/defaults/Core_Testnet.toml
@@ -1,6 +1,7 @@
#Core Testnet
ChainID = '1114'
FinalityDepth = 7 # finality harcoded based on validator size of the network
+LinkContractAddress = '0x6C475841d1D7871940E93579E5DBaE01634e17aA'
LogPollInterval = '3s' # block rate 3s
[GasEstimator]
diff --git a/evm/config/toml/defaults/Corn_Mainnet.toml b/evm/config/toml/defaults/Corn_Mainnet.toml
index 32e75715de9..b1a1403edf5 100644
--- a/evm/config/toml/defaults/Corn_Mainnet.toml
+++ b/evm/config/toml/defaults/Corn_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '21000000'
-FinalityTagEnabled = true
ChainType = 'arbitrum'
+FinalityTagEnabled = true
+LinkContractAddress = '0x7311DED199CC28D80E58e81e8589aa160199FCD2'
[GasEstimator]
Mode = 'Arbitrum'
diff --git a/evm/config/toml/defaults/Corn_Testnet.toml b/evm/config/toml/defaults/Corn_Testnet.toml
index 8f0f95804d4..5e7fbe3b4b2 100644
--- a/evm/config/toml/defaults/Corn_Testnet.toml
+++ b/evm/config/toml/defaults/Corn_Testnet.toml
@@ -1,6 +1,7 @@
ChainID = '21000001'
-FinalityTagEnabled = true
ChainType = 'arbitrum'
+FinalityTagEnabled = true
+LinkContractAddress = '0x996EfAb6011896Be832969D91E9bc1b3983cfdA1'
[GasEstimator]
Mode = 'Arbitrum'
diff --git a/evm/config/toml/defaults/Ethereum_Holesky.toml b/evm/config/toml/defaults/Ethereum_Holesky.toml
index 18480e17df2..fe782cb876c 100644
--- a/evm/config/toml/defaults/Ethereum_Holesky.toml
+++ b/evm/config/toml/defaults/Ethereum_Holesky.toml
@@ -1,5 +1,6 @@
ChainID = '17000'
FinalityTagEnabled = true
+LinkContractAddress = '0x685cE6742351ae9b618F383883D6d1e0c5A31B4B'
[GasEstimator]
EIP1559DynamicFees = true
diff --git a/evm/config/toml/defaults/Gnosis_Chiado.toml b/evm/config/toml/defaults/Gnosis_Chiado.toml
index 4e54210455f..cf72f236602 100644
--- a/evm/config/toml/defaults/Gnosis_Chiado.toml
+++ b/evm/config/toml/defaults/Gnosis_Chiado.toml
@@ -1,7 +1,8 @@
ChainID = '10200'
-# Gnoisis Finality is approx 8 minutes @ 12 blocks per minute, so 96 blocks
-FinalityDepth = 100
ChainType = 'gnosis'
+# Gnosis Finality is approx 8 minutes @ 12 blocks per minute, so 96 blocks
+FinalityDepth = 100
+LinkContractAddress = '0xDCA67FD8324990792C0bfaE95903B8A64097754F'
LogPollInterval = '5s'
FinalizedBlockOffset = 2
NoNewFinalizedHeadsThreshold = '2m'
diff --git a/evm/config/toml/defaults/Hashkey_Mainnet.toml b/evm/config/toml/defaults/Hashkey_Mainnet.toml
index 6e4734d3ebd..2ba3766a007 100644
--- a/evm/config/toml/defaults/Hashkey_Mainnet.toml
+++ b/evm/config/toml/defaults/Hashkey_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '177'
ChainType = 'optimismBedrock'
FinalityTagEnabled = true
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
[GasEstimator]
PriceMax = '1000 gwei'
diff --git a/evm/config/toml/defaults/Hashkey_Testnet.toml b/evm/config/toml/defaults/Hashkey_Testnet.toml
index 6b25161867e..3b100a6cd46 100644
--- a/evm/config/toml/defaults/Hashkey_Testnet.toml
+++ b/evm/config/toml/defaults/Hashkey_Testnet.toml
@@ -1,6 +1,7 @@
ChainID = '133'
ChainType = 'optimismBedrock'
FinalityTagEnabled = true
+LinkContractAddress = '0x8418c4d7e8e17ab90232DC72150730E6c4b84F57'
[GasEstimator]
PriceMax = '1000 gwei'
diff --git a/evm/config/toml/defaults/Hedera_Mainnet.toml b/evm/config/toml/defaults/Hedera_Mainnet.toml
index 591e486a8ec..98015b39da7 100644
--- a/evm/config/toml/defaults/Hedera_Mainnet.toml
+++ b/evm/config/toml/defaults/Hedera_Mainnet.toml
@@ -3,6 +3,7 @@ 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
+LinkContractAddress = '0x7Ce6bb2Cc2D3Fd45a974Da6a0F29236cb9513a98'
# Hedera has high TPS, so polling less often
LogPollInterval = '10s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Hedera_Testnet.toml b/evm/config/toml/defaults/Hedera_Testnet.toml
index 0e2f2c7cd2c..c266d3187c7 100644
--- a/evm/config/toml/defaults/Hedera_Testnet.toml
+++ b/evm/config/toml/defaults/Hedera_Testnet.toml
@@ -3,6 +3,7 @@ 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
+LinkContractAddress = '0x90a386d59b9A6a4795a011e8f032Fc21ED6FEFb6'
# Hedera has high TPS, so polling less often
LogPollInterval = '10s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Ink_Mainnet.toml b/evm/config/toml/defaults/Ink_Mainnet.toml
index d4b35f291d9..b202b60432e 100644
--- a/evm/config/toml/defaults/Ink_Mainnet.toml
+++ b/evm/config/toml/defaults/Ink_Mainnet.toml
@@ -3,6 +3,7 @@ ChainID = '57073'
ChainType = 'optimismBedrock'
# finality_depth was: ~2094
FinalityDepth = 3000
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
# block_time was: ~1s, adding 1 second buffer
LogPollInterval = '2s'
diff --git a/evm/config/toml/defaults/Ink_Testnet.toml b/evm/config/toml/defaults/Ink_Testnet.toml
index 936651bfb0c..543eaf26f31 100644
--- a/evm/config/toml/defaults/Ink_Testnet.toml
+++ b/evm/config/toml/defaults/Ink_Testnet.toml
@@ -3,6 +3,7 @@ ChainID = '763373'
ChainType = 'optimismBedrock'
# finality_depth was: ~2094
FinalityDepth = 3000
+LinkContractAddress = '0x3423C922911956b1Ccbc2b5d4f38216a6f4299b4'
# block_time was: ~1s, adding 1 second buffer
LogPollInterval = '2s'
diff --git a/evm/config/toml/defaults/Kroma_Mainnet.toml b/evm/config/toml/defaults/Kroma_Mainnet.toml
index c832d666aa6..f2448e92777 100644
--- a/evm/config/toml/defaults/Kroma_Mainnet.toml
+++ b/evm/config/toml/defaults/Kroma_Mainnet.toml
@@ -2,6 +2,7 @@ ChainID = '255'
ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture
FinalityDepth = 400
FinalityTagEnabled = true
+LinkContractAddress = '0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450'
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Kroma_Sepolia.toml b/evm/config/toml/defaults/Kroma_Sepolia.toml
index b0864d86c90..2ca1eda1e3b 100644
--- a/evm/config/toml/defaults/Kroma_Sepolia.toml
+++ b/evm/config/toml/defaults/Kroma_Sepolia.toml
@@ -2,6 +2,7 @@ ChainID = '2358'
ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture
FinalityDepth = 400
FinalityTagEnabled = true
+LinkContractAddress = '0xa75cCA5b404ec6F4BB6EC4853D177FE7057085c8'
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Lens_Sepolia.toml b/evm/config/toml/defaults/Lens_Sepolia.toml
index 7830f89101b..40c05d3a162 100644
--- a/evm/config/toml/defaults/Lens_Sepolia.toml
+++ b/evm/config/toml/defaults/Lens_Sepolia.toml
@@ -2,7 +2,8 @@ ChainID = "37111"
ChainType = "zksync"
# finality depth for this chain is very inconsistent due to low network traffic. in testing blocks every ~1-2minutes were seen
# confirmed this value with product
-FinalityDepth = 40
+FinalityDepth = 40
+LinkContractAddress = '0x7f1b9eE544f9ff9bB521Ab79c205d79C55250a36'
# block rate is dynamic, have seen block times as low as 1s
LogPollInterval = "5s"
# sufficient time for RPC to be labelled out of sync
diff --git a/evm/config/toml/defaults/Linea_Mainnet.toml b/evm/config/toml/defaults/Linea_Mainnet.toml
index 5a89873acae..ca840d8bc95 100644
--- a/evm/config/toml/defaults/Linea_Mainnet.toml
+++ b/evm/config/toml/defaults/Linea_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '59144'
# Block time 12s, finality < 60m
FinalityDepth = 300
+LinkContractAddress = '0xa18152629128738a5c081eb226335FEd4B9C95e9'
# Blocks are only emitted when a transaction happens / no empty blocks
NoNewHeadsThreshold = '0'
diff --git a/evm/config/toml/defaults/Linea_Sepolia.toml b/evm/config/toml/defaults/Linea_Sepolia.toml
index 8f168ee93a6..a4c0a559fb8 100644
--- a/evm/config/toml/defaults/Linea_Sepolia.toml
+++ b/evm/config/toml/defaults/Linea_Sepolia.toml
@@ -1,5 +1,6 @@
ChainID = '59141'
FinalityDepth = 900
+LinkContractAddress = '0xF64E6E064a71B45514691D397ad4204972cD6508'
NoNewHeadsThreshold = '0'
[GasEstimator]
diff --git a/evm/config/toml/defaults/Mantle_Mainnet.toml b/evm/config/toml/defaults/Mantle_Mainnet.toml
index 33a34184f0b..6006a2fee0b 100644
--- a/evm/config/toml/defaults/Mantle_Mainnet.toml
+++ b/evm/config/toml/defaults/Mantle_Mainnet.toml
@@ -1,7 +1,8 @@
ChainID = '5000'
+ChainType = 'optimismBedrock'
FinalityTagEnabled = true
FinalityDepth = 1200
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0xfe36cF0B43aAe49fBc5cFC5c0AF22a623114E043'
LogPollInterval = '2s'
MinIncomingConfirmations = 1
NoNewFinalizedHeadsThreshold = '40m0s'
diff --git a/evm/config/toml/defaults/Mantle_Sepolia.toml b/evm/config/toml/defaults/Mantle_Sepolia.toml
index bdfa4a204f8..2e3e76c6713 100644
--- a/evm/config/toml/defaults/Mantle_Sepolia.toml
+++ b/evm/config/toml/defaults/Mantle_Sepolia.toml
@@ -1,7 +1,8 @@
ChainID = '5003'
+ChainType = 'optimismBedrock'
FinalityTagEnabled = true
FinalityDepth = 1200
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0x22bdEdEa0beBdD7CfFC95bA53826E55afFE9DE04'
LogPollInterval = '2s'
MinIncomingConfirmations = 1
NoNewFinalizedHeadsThreshold = '60m0s'
diff --git a/evm/config/toml/defaults/Metis_Mainnet.toml b/evm/config/toml/defaults/Metis_Mainnet.toml
index 2b800e55090..0869b972925 100644
--- a/evm/config/toml/defaults/Metis_Mainnet.toml
+++ b/evm/config/toml/defaults/Metis_Mainnet.toml
@@ -4,6 +4,7 @@ ChainType = 'optimismBedrock'
# Sequencer offers absolute finality
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0xd2FE54D1E5F568eB710ba9d898Bf4bD02C7c0353'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
diff --git a/evm/config/toml/defaults/Metis_Sepolia.toml b/evm/config/toml/defaults/Metis_Sepolia.toml
index 4ff4056c75d..028bc663d00 100644
--- a/evm/config/toml/defaults/Metis_Sepolia.toml
+++ b/evm/config/toml/defaults/Metis_Sepolia.toml
@@ -2,6 +2,7 @@ ChainID = '59902'
ChainType = 'optimismBedrock'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x9870D6a0e05F867EAAe696e106741843F7fD116D'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '0'
OCR.ContractConfirmations = 1
diff --git a/evm/config/toml/defaults/Mode_Mainnet.toml b/evm/config/toml/defaults/Mode_Mainnet.toml
index 7ab92813742..dd65fe04c80 100644
--- a/evm/config/toml/defaults/Mode_Mainnet.toml
+++ b/evm/config/toml/defaults/Mode_Mainnet.toml
@@ -1,7 +1,8 @@
ChainID = '34443'
+ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0x183E3691EfF3524B2315D3703D94F922CbE51F54'
[GasEstimator]
EIP1559DynamicFees = true
diff --git a/evm/config/toml/defaults/Mode_Sepolia.toml b/evm/config/toml/defaults/Mode_Sepolia.toml
index 4371138ec17..2a06cf8074c 100644
--- a/evm/config/toml/defaults/Mode_Sepolia.toml
+++ b/evm/config/toml/defaults/Mode_Sepolia.toml
@@ -1,7 +1,8 @@
ChainID = '919'
+ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
-ChainType = 'optimismBedrock'
+LinkContractAddress = '0x925a4bfE64AE2bFAC8a02b35F78e60C29743755d'
[GasEstimator]
EIP1559DynamicFees = true
diff --git a/evm/config/toml/defaults/Optimism_Sepolia.toml b/evm/config/toml/defaults/Optimism_Sepolia.toml
index ff367df0feb..e16ffd1ced7 100644
--- a/evm/config/toml/defaults/Optimism_Sepolia.toml
+++ b/evm/config/toml/defaults/Optimism_Sepolia.toml
@@ -2,6 +2,7 @@ ChainID = '11155420'
ChainType = 'optimismBedrock'
FinalityDepth = 200
FinalityTagEnabled = true
+LinkContractAddress = '0xE4aB69C077896252FAFBD49EFD26B5D171A32410'
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
MinIncomingConfirmations = 1
diff --git a/evm/config/toml/defaults/Polygon_Amoy.toml b/evm/config/toml/defaults/Polygon_Amoy.toml
index bca42d9b403..7026c72dfdd 100644
--- a/evm/config/toml/defaults/Polygon_Amoy.toml
+++ b/evm/config/toml/defaults/Polygon_Amoy.toml
@@ -1,5 +1,6 @@
ChainID = '80002'
FinalityDepth = 500
+LinkContractAddress = '0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904'
LogPollInterval = '1s'
MinIncomingConfirmations = 5
NoNewHeadsThreshold = '30s'
diff --git a/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml b/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml
index 5e5bc573706..35e167b897e 100644
--- a/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml
+++ b/evm/config/toml/defaults/Polygon_Zkevm_Cardona.toml
@@ -1,9 +1,10 @@
ChainID = '2442'
ChainType = 'zkevm'
FinalityDepth = 500
-NoNewHeadsThreshold = '12m'
-MinIncomingConfirmations = 1
+LinkContractAddress = '0x5576815a38A3706f37bf815b261cCc7cCA77e975'
LogPollInterval = '30s'
+MinIncomingConfirmations = 1
+NoNewHeadsThreshold = '12m'
RPCDefaultBatchSize = 100
[OCR]
diff --git a/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml b/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml
index 1952c40d590..3aa0bddbb86 100644
--- a/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml
+++ b/evm/config/toml/defaults/Polygon_Zkevm_Mainnet.toml
@@ -1,9 +1,10 @@
ChainID = '1101'
ChainType = 'zkevm'
FinalityDepth = 500
-NoNewHeadsThreshold = '6m'
-MinIncomingConfirmations = 1
+LinkContractAddress = '0xdB7A504CF869484dd6aC5FaF925c8386CBF7573D'
LogPollInterval = '30s'
+MinIncomingConfirmations = 1
+NoNewHeadsThreshold = '6m'
RPCBlockQueryDelay = 15
RPCDefaultBatchSize = 100
diff --git a/evm/config/toml/defaults/Scroll_Mainnet.toml b/evm/config/toml/defaults/Scroll_Mainnet.toml
index 6a7441201ae..ad7d06b675b 100644
--- a/evm/config/toml/defaults/Scroll_Mainnet.toml
+++ b/evm/config/toml/defaults/Scroll_Mainnet.toml
@@ -1,7 +1,8 @@
ChainID = '534352'
+ChainType = 'scroll'
FinalityDepth = 10
FinalityTagEnabled = true
-ChainType = 'scroll'
+LinkContractAddress = '0x548C6944cba02B9D1C0570102c89de64D258d3Ac'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
# Scroll only emits blocks when a new tx is received, so this method of liveness detection is not useful
diff --git a/evm/config/toml/defaults/Scroll_Sepolia.toml b/evm/config/toml/defaults/Scroll_Sepolia.toml
index 1351bf73ded..93e48b0e2b1 100644
--- a/evm/config/toml/defaults/Scroll_Sepolia.toml
+++ b/evm/config/toml/defaults/Scroll_Sepolia.toml
@@ -1,7 +1,8 @@
ChainID = '534351'
+ChainType = 'scroll'
FinalityDepth = 10
FinalityTagEnabled = true
-ChainType = 'scroll'
+LinkContractAddress = '0x231d45b53C905c3d6201318156BDC725c9c3B9B1'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
# Scroll only emits blocks when a new tx is received, so this method of liveness detection is not useful
diff --git a/evm/config/toml/defaults/Soneium_Mainnet.toml b/evm/config/toml/defaults/Soneium_Mainnet.toml
index 9dd633123cb..e1a28009e26 100644
--- a/evm/config/toml/defaults/Soneium_Mainnet.toml
+++ b/evm/config/toml/defaults/Soneium_Mainnet.toml
@@ -1,6 +1,6 @@
ChainID = '1868'
ChainType = 'optimismBedrock'
-LinkContractAddress = '0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2'
+LinkContractAddress = '0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec'
FinalityDepth = 200
LogPollInterval = '2s'
NoNewHeadsThreshold = '40s'
diff --git a/evm/config/toml/defaults/Sonic_Mainnet.toml b/evm/config/toml/defaults/Sonic_Mainnet.toml
index 1d6aa4e88b5..0e5a4919dcd 100644
--- a/evm/config/toml/defaults/Sonic_Mainnet.toml
+++ b/evm/config/toml/defaults/Sonic_Mainnet.toml
@@ -1,6 +1,7 @@
ChainId = '146'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x71052BAe71C25C78E37fD12E5ff1101A71d9018F'
LogPollInterval = "1s" #1s block rate
MinIncomingConfirmations = 5
RPCBlockQueryDelay = 10
diff --git a/evm/config/toml/defaults/Sonic_Testnet.toml b/evm/config/toml/defaults/Sonic_Testnet.toml
index a077bd68390..3a8210954ab 100644
--- a/evm/config/toml/defaults/Sonic_Testnet.toml
+++ b/evm/config/toml/defaults/Sonic_Testnet.toml
@@ -1,6 +1,7 @@
ChainId = '57054'
FinalityDepth = 10
FinalityTagEnabled = false
+LinkContractAddress = '0x61876F0429726D7777B46f663e1C9ab75d08Fc56'
LogPollInterval = "1s" #1s block rate
MinIncomingConfirmations = 5
RPCBlockQueryDelay = 10
diff --git a/evm/config/toml/defaults/Unichain_Testnet.toml b/evm/config/toml/defaults/Unichain_Testnet.toml
index 6754f49a569..c8b9a493467 100644
--- a/evm/config/toml/defaults/Unichain_Testnet.toml
+++ b/evm/config/toml/defaults/Unichain_Testnet.toml
@@ -3,6 +3,7 @@ ChainID = '1301'
ChainType = 'optimismBedrock'
# finality_depth was: ~1900
FinalityDepth = 2000
+LinkContractAddress = '0xda40816f278Cd049c137F6612822D181065EBfB4'
# block_time was: ~1s, adding 1 second buffer
LogPollInterval = '2s'
diff --git a/evm/config/toml/defaults/WeMix_Mainnet.toml b/evm/config/toml/defaults/WeMix_Mainnet.toml
index 8af3f1bb9e5..b147ce4b066 100644
--- a/evm/config/toml/defaults/WeMix_Mainnet.toml
+++ b/evm/config/toml/defaults/WeMix_Mainnet.toml
@@ -2,6 +2,7 @@ ChainID = '1111'
ChainType = 'wemix'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x80f1FcdC96B55e459BF52b998aBBE2c364935d69'
MinIncomingConfirmations = 1
# WeMix emits a block every 1 second, regardless of transactions
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/WeMix_Testnet.toml b/evm/config/toml/defaults/WeMix_Testnet.toml
index 451d22a1557..4416c3587bd 100644
--- a/evm/config/toml/defaults/WeMix_Testnet.toml
+++ b/evm/config/toml/defaults/WeMix_Testnet.toml
@@ -2,6 +2,7 @@ ChainID = '1112'
ChainType = 'wemix'
FinalityDepth = 10
FinalityTagEnabled = true
+LinkContractAddress = '0x3580c7A817cCD41f7e02143BFa411D4EeAE78093'
MinIncomingConfirmations = 1
# WeMix emits a block every 1 second, regardless of transactions
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/Worldchain_Mainnet.toml b/evm/config/toml/defaults/Worldchain_Mainnet.toml
index 24647e19fd6..d7fe3b7c180 100644
--- a/evm/config/toml/defaults/Worldchain_Mainnet.toml
+++ b/evm/config/toml/defaults/Worldchain_Mainnet.toml
@@ -3,6 +3,7 @@ ChainID = '480'
ChainType = 'optimismBedrock'
# finality_depth was: ~2400
FinalityDepth = 2500
+LinkContractAddress = '0x915b648e994d5f31059B38223b9fbe98ae185473'
# block_time was: 2s, adding 1 second buffer
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/Worldchain_Testnet.toml b/evm/config/toml/defaults/Worldchain_Testnet.toml
index 293584bb6ca..e32c2a7ddb3 100644
--- a/evm/config/toml/defaults/Worldchain_Testnet.toml
+++ b/evm/config/toml/defaults/Worldchain_Testnet.toml
@@ -3,6 +3,7 @@ ChainID = '4801'
ChainType = 'optimismBedrock'
# finality_depth was: ~2400
FinalityDepth = 2500
+LinkContractAddress = '0xC82Ea35634BcE95C394B6BC00626f827bB0F4801'
# block_time was: 2s, adding 1 second buffer
LogPollInterval = '3s'
diff --git a/evm/config/toml/defaults/XLayer_Mainnet.toml b/evm/config/toml/defaults/XLayer_Mainnet.toml
index 1d96e95e10d..42fefa4191b 100644
--- a/evm/config/toml/defaults/XLayer_Mainnet.toml
+++ b/evm/config/toml/defaults/XLayer_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '196'
ChainType = 'xlayer'
FinalityDepth = 500
+LinkContractAddress = '0x8aF9711B44695a5A081F25AB9903DDB73aCf8FA9'
NoNewHeadsThreshold = '6m'
MinIncomingConfirmations = 1
LogPollInterval = '30s'
diff --git a/evm/config/toml/defaults/XLayer_Sepolia.toml b/evm/config/toml/defaults/XLayer_Sepolia.toml
index 3f4a5debde5..684e188c074 100644
--- a/evm/config/toml/defaults/XLayer_Sepolia.toml
+++ b/evm/config/toml/defaults/XLayer_Sepolia.toml
@@ -1,6 +1,7 @@
ChainID = '195'
ChainType = 'xlayer'
FinalityDepth = 500
+LinkContractAddress = '0x724593f6FCb0De4E6902d4C55D7C74DaA2AF0E55'
NoNewHeadsThreshold = '12m'
MinIncomingConfirmations = 1
LogPollInterval = '30s'
diff --git a/evm/config/toml/defaults/zkSync_Goerli.toml b/evm/config/toml/defaults/ZKsync_Goerli.toml
similarity index 81%
rename from evm/config/toml/defaults/zkSync_Goerli.toml
rename to evm/config/toml/defaults/ZKsync_Goerli.toml
index 035eec62d49..a521eb8187f 100644
--- a/evm/config/toml/defaults/zkSync_Goerli.toml
+++ b/evm/config/toml/defaults/ZKsync_Goerli.toml
@@ -1,6 +1,7 @@
ChainID = '280'
ChainType = 'zksync'
FinalityDepth = 10
+LinkContractAddress = '0xD29F4Cc763A064b6C563B8816f09351b3Fbb61A0'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '1m'
diff --git a/evm/config/toml/defaults/zkSync_Mainnet.toml b/evm/config/toml/defaults/ZKsync_Mainnet.toml
similarity index 84%
rename from evm/config/toml/defaults/zkSync_Mainnet.toml
rename to evm/config/toml/defaults/ZKsync_Mainnet.toml
index c4e0cef4c61..da750a009f2 100644
--- a/evm/config/toml/defaults/zkSync_Mainnet.toml
+++ b/evm/config/toml/defaults/ZKsync_Mainnet.toml
@@ -1,6 +1,7 @@
ChainID = '324'
ChainType = 'zksync'
FinalityDepth = 10
+LinkContractAddress = '0x52869bae3E091e36b0915941577F2D47d8d8B534'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '1m'
diff --git a/evm/config/toml/defaults/zkSync_Sepolia.toml b/evm/config/toml/defaults/ZKsync_Sepolia.toml
similarity index 84%
rename from evm/config/toml/defaults/zkSync_Sepolia.toml
rename to evm/config/toml/defaults/ZKsync_Sepolia.toml
index ed7c37b8ca1..ff66ad98e5f 100644
--- a/evm/config/toml/defaults/zkSync_Sepolia.toml
+++ b/evm/config/toml/defaults/ZKsync_Sepolia.toml
@@ -1,6 +1,7 @@
ChainID = '300'
ChainType = 'zksync'
FinalityDepth = 10
+LinkContractAddress = '0x23A1aFD896c8c8876AF46aDc38521f4432658d1e'
LogPollInterval = '5s'
MinIncomingConfirmations = 1
NoNewHeadsThreshold = '1m'
diff --git a/evm/gas/fee_history_estimator_test.go b/evm/gas/fee_history_estimator_test.go
index 8371db8fac1..ae3bb6452f0 100644
--- a/evm/gas/fee_history_estimator_test.go
+++ b/evm/gas/fee_history_estimator_test.go
@@ -65,7 +65,7 @@ func TestFeeHistoryEstimatorLifecycle(t *testing.T) {
CacheTimeout: 10 * time.Second,
}
- u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil)
+ u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil)
err := u.Start(tests.Context(t))
assert.NoError(t, err)
err = u.Close()
diff --git a/evm/testutils/config.go b/evm/testutils/config.go
index e95541bd276..e1b85905606 100644
--- a/evm/testutils/config.go
+++ b/evm/testutils/config.go
@@ -3,8 +3,6 @@ package testutils
import (
"testing"
- "github.com/smartcontractkit/chainlink-common/pkg/logger"
-
"github.com/smartcontractkit/chainlink/v2/evm/config"
"github.com/smartcontractkit/chainlink/v2/evm/config/toml"
"github.com/smartcontractkit/chainlink/v2/evm/utils/big"
@@ -26,5 +24,5 @@ func NewTestChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig))
overrideFn(evmCfg)
}
- return config.NewTOMLChainScopedConfig(evmCfg, logger.Test(t))
+ return config.NewTOMLChainScopedConfig(evmCfg)
}
diff --git a/evm/testutils/evmtypes.go b/evm/testutils/evmtypes.go
index a7358df0a40..a99b7278161 100644
--- a/evm/testutils/evmtypes.go
+++ b/evm/testutils/evmtypes.go
@@ -6,9 +6,13 @@ import (
"math"
"math/big"
mrand "math/rand"
+ "testing"
+ "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/stretchr/testify/require"
evmtypes "github.com/smartcontractkit/chainlink/v2/evm/types"
evmutils "github.com/smartcontractkit/chainlink/v2/evm/utils"
@@ -89,3 +93,13 @@ func NewAddressPtr() *common.Address {
a := common.BytesToAddress(randomBytes(20))
return &a
}
+
+// MustNewSimTransactor returns a transactor for interacting with the
+// geth simulated backend.
+func MustNewSimTransactor(t testing.TB) *bind.TransactOpts {
+ key, err := crypto.GenerateKey()
+ require.NoError(t, err)
+ transactor, err := bind.NewKeyedTransactorWithChainID(key, SimulatedChainID)
+ require.NoError(t, err)
+ return transactor
+}
diff --git a/evm/testutils/sql.go b/evm/testutils/sql.go
new file mode 100644
index 00000000000..3c2e2a82d51
--- /dev/null
+++ b/evm/testutils/sql.go
@@ -0,0 +1,66 @@
+package testutils
+
+import (
+ "net/url"
+ "os"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/jmoiron/sqlx"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils"
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+)
+
+func NewSqlxDB(t testing.TB) *sqlx.DB {
+ SkipShortDB(t)
+ dbURL := os.Getenv("CL_DATABASE_URL")
+ if dbURL == "" {
+ t.Errorf("you must provide a CL_DATABASE_URL environment variable")
+ return nil
+ }
+ return sqltest.NewDB(t, dbURL)
+}
+
+// SkipShortDB skips tb during -short runs, and notes the DB dependency.
+func SkipShortDB(tb testing.TB) {
+ tests.SkipShort(tb, "DB dependency")
+}
+
+func MustExec(t *testing.T, ds sqlutil.DataSource, stmt string, args ...interface{}) {
+ require.NoError(t, utils.JustError(ds.ExecContext(Context(t), stmt, args...)))
+}
+
+// pristineDBName is a clean copy of test DB with migrations.
+const pristineDBName = "chainlink_test_pristine" //TODO update when splitting schemas
+
+// NewIndependentSqlxDB return a new independent test database, which does not use txdb and therefore supports txs etc.
+// Use this with caution, as it is much more costly than NewSqlxDB.
+func NewIndependentSqlxDB(t testing.TB) *sqlx.DB {
+ SkipShortDB(t)
+
+ ctx := tests.Context(t)
+
+ dbURL, err := url.Parse(sqltest.TestURL(t))
+ require.NoError(t, err)
+ dbName := "chainlink_test_" + strings.ReplaceAll(uuid.NewString(), "-", "")
+ newDBURL := sqltest.CreateOrReplace(t, *dbURL, dbName, pristineDBName)
+
+ db, err := pg.DBConfig{
+ IdleInTxSessionTimeout: time.Hour,
+ LockTimeout: 15 * time.Second,
+ MaxOpenConns: 100,
+ MaxIdleConns: 10,
+ }.New(ctx, newDBURL.String(), pg.DriverPostgres)
+ require.NoError(t, err)
+ t.Cleanup(func() { assert.NoError(t, db.Close()) })
+
+ return db
+}
diff --git a/evm/testutils/testutils.go b/evm/testutils/testutils.go
new file mode 100644
index 00000000000..b410360d6a4
--- /dev/null
+++ b/evm/testutils/testutils.go
@@ -0,0 +1,45 @@
+package testutils
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+)
+
+// Context returns a context with the test's deadline, if available.
+func Context(tb testing.TB) context.Context {
+ return tests.Context(tb)
+}
+
+// DefaultWaitTimeout is the default wait timeout. If you have a *testing.T, use WaitTimeout instead.
+const DefaultWaitTimeout = 30 * time.Second
+
+// WaitTimeout returns a timeout based on the test's Deadline, if available.
+// Especially important to use in parallel tests, as their individual execution
+// can get paused for arbitrary amounts of time.
+func WaitTimeout(t *testing.T) time.Duration {
+ if d, ok := t.Deadline(); ok {
+ // 10% buffer for cleanup and scheduling delay
+ return time.Until(d) * 9 / 10
+ }
+ return DefaultWaitTimeout
+}
+
+// TestInterval is just a sensible poll interval that gives fast tests without
+// risk of spamming
+const TestInterval = 100 * time.Millisecond
+
+// 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)
+}
diff --git a/go.md b/go.md
index d361331b328..a05a9720c1c 100644
--- a/go.md
+++ b/go.md
@@ -33,7 +33,7 @@ flowchart LR
chainlink-common --> grpc-proxy
chainlink-common --> libocr
click chainlink-common href "https://github.com/smartcontractkit/chainlink-common"
- chainlink-cosmos --> chainlink-common
+ chainlink-cosmos --> chainlink-framework/chains
click chainlink-cosmos href "https://github.com/smartcontractkit/chainlink-cosmos"
chainlink-data-streams --> chainlink-common
click chainlink-data-streams href "https://github.com/smartcontractkit/chainlink-data-streams"
@@ -57,7 +57,6 @@ flowchart LR
chainlink/v2 --> chainlink-cosmos
chainlink/v2 --> chainlink-data-streams
chainlink/v2 --> chainlink-feeds
- chainlink/v2 --> chainlink-framework/chains
chainlink/v2 --> chainlink-protos/orchestrator
chainlink/v2 --> chainlink-protos/svr
chainlink/v2 --> chainlink-solana
@@ -139,7 +138,7 @@ flowchart LR
chainlink-common --> grpc-proxy
chainlink-common --> libocr
click chainlink-common href "https://github.com/smartcontractkit/chainlink-common"
- chainlink-cosmos --> chainlink-common
+ chainlink-cosmos --> chainlink-framework/chains
click chainlink-cosmos href "https://github.com/smartcontractkit/chainlink-cosmos"
chainlink-data-streams --> chainlink-common
click chainlink-data-streams href "https://github.com/smartcontractkit/chainlink-data-streams"
@@ -191,7 +190,6 @@ flowchart LR
chainlink/v2 --> chainlink-cosmos
chainlink/v2 --> chainlink-data-streams
chainlink/v2 --> chainlink-feeds
- chainlink/v2 --> chainlink-framework/chains
chainlink/v2 --> chainlink-protos/orchestrator
chainlink/v2 --> chainlink-protos/svr
chainlink/v2 --> chainlink-solana
diff --git a/go.mod b/go.mod
index 159557eda5b..721eb5db8c2 100644
--- a/go.mod
+++ b/go.mod
@@ -77,15 +77,15 @@ require (
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.36
+ github.com/smartcontractkit/chain-selectors v1.0.37
github.com/smartcontractkit/chainlink-automation v0.8.1
- github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847
- github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b
- github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36
- github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4
- github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3
+ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9
+ github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b
+ github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36
+ github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc
+ github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5
github.com/smartcontractkit/chainlink-feeds v0.1.1
- github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92
+ github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0
github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250121222331-a7010b4b8ce5
@@ -124,7 +124,7 @@ require (
golang.org/x/tools v0.28.0
gonum.org/v1/gonum v0.15.1
google.golang.org/grpc v1.67.1
- google.golang.org/protobuf v1.35.1
+ google.golang.org/protobuf v1.36.4
gopkg.in/guregu/null.v4 v4.0.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
@@ -407,4 +407,5 @@ replace (
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
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 113ab6eef20..b3d3c2bcf81 100644
--- a/go.sum
+++ b/go.sum
@@ -1102,24 +1102,24 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
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.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0=
-github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 h1:kCcrM/osIQFmHx7ZOxeGIeYAMkSmTxkOXcmqHNlXQXQ=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 h1:+/KEPuWctPObgOoEEBCnli1/H3XnjMdCY3Tn+J32XRM=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b h1:eNsqumP7VVJudA7gEcTKVFofealwbPJRinUw24uEmII=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 h1:w7w42ml8MOxdoyAZ9+og0342UkiH3deRM1V0Pj5JR5g=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4/go.mod h1:wtdAmAUMooLavbrTA7PgHg40lyDlKesxI/RR+5Xcz18=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36 h1:bS51NFGHVjkCy7yu9L2Ss4sBsCW6jpa5GuhRAdWWxzM=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc h1:WZERXv2hTYRA0NpWg79ci/ZZSxucmvkty39iUOV8d7I=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc/go.mod h1:2iGmU7fkVsy21Sw8D+OhtYekHLUlJKHzwePKcxIx3Ac=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 h1:CvDfgWoLoYPapOumE/UZCplfCu5oNmy9BuH+6V6+fJ8=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c=
github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a h1:fVtn9CDfoGF40FeqGwLvp9belfIw7VT3lgQTctFGP5E=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU=
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ=
@@ -1834,8 +1834,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
-google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/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=
diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go
index 7b2e4506912..90fca00d19e 100644
--- a/integration-tests/ccip-tests/actions/ccip_helpers.go
+++ b/integration-tests/ccip-tests/actions/ccip_helpers.go
@@ -57,6 +57,7 @@ import (
"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/maybe_revert_message_receiver"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
@@ -1897,26 +1898,28 @@ func (sourceCCIP *SourceCCIPModule) CCIPMsg(
func (sourceCCIP *SourceCCIPModule) SendRequest(
receiver common.Address,
gasLimit *big.Int,
-) (common.Hash, time.Duration, *big.Int, error) {
+) (common.Hash, time.Duration, *big.Int, []byte, error) {
var d time.Duration
destChainSelector, err := chainselectors.SelectorFromChainId(sourceCCIP.DestinationChainId)
if err != nil {
- return common.Hash{}, d, nil, fmt.Errorf("failed getting the chain selector: %w", err)
+ return common.Hash{}, d, nil, nil, fmt.Errorf("failed getting the chain selector: %w", err)
}
// form the message for transfer
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)
+ return common.Hash{}, d, nil, nil, fmt.Errorf("failed forming the ccip msg: %w", err)
}
+ msgData := msg.Data
+
fee, err := sourceCCIP.Common.Router.GetFee(destChainSelector, msg)
if err != nil {
log.Info().Interface("Msg", msg).Msg("CCIP msg")
reason, _ := blockchain.RPCErrorFromError(err)
if reason != "" {
- return common.Hash{}, d, nil, fmt.Errorf("failed getting the fee: %s", reason)
+ return common.Hash{}, d, nil, msgData, fmt.Errorf("failed getting the fee: %s", reason)
}
- return common.Hash{}, d, nil, fmt.Errorf("failed getting the fee: %w", err)
+ return common.Hash{}, d, nil, nil, fmt.Errorf("failed getting the fee: %w", err)
}
log.Info().Str("Fee", fee.String()).Msg("Calculated fee")
@@ -1932,7 +1935,7 @@ func (sourceCCIP *SourceCCIPModule) SendRequest(
if sendTx != nil {
txHash = sendTx.Hash()
}
- return txHash, time.Since(timeNow), nil, fmt.Errorf("failed initiating the transfer ccip-send: %w", err)
+ return txHash, time.Since(timeNow), nil, nil, fmt.Errorf("failed initiating the transfer ccip-send: %w", err)
}
} else {
sendTx, err = sourceCCIP.Common.Router.CCIPSendAndProcessTx(destChainSelector, msg, fee)
@@ -1941,7 +1944,7 @@ func (sourceCCIP *SourceCCIPModule) SendRequest(
if sendTx != nil {
txHash = sendTx.Hash()
}
- return txHash, time.Since(timeNow), nil, fmt.Errorf("failed initiating the transfer ccip-send: %w", err)
+ return txHash, time.Since(timeNow), nil, nil, fmt.Errorf("failed initiating the transfer ccip-send: %w", err)
}
}
@@ -1950,7 +1953,7 @@ func (sourceCCIP *SourceCCIPModule) SendRequest(
Str("Send token transaction", sendTx.Hash().String()).
Str("lane", fmt.Sprintf("%s-->%s", sourceCCIP.Common.ChainClient.GetNetworkName(), sourceCCIP.DestNetworkName)).
Msg("Sending token")
- return sendTx.Hash(), time.Since(timeNow), fee, nil
+ return sendTx.Hash(), time.Since(timeNow), fee, msgData, nil
}
func DefaultSourceCCIPModule(
@@ -1996,6 +1999,7 @@ type DestCCIPModule struct {
OffRamp *contracts.OffRamp
ReportAcceptedWatcher *sync.Map
ExecStateChangedWatcher *sync.Map
+ MessageReceivedWatcher *sync.Map
ReportBlessedWatcher *sync.Map
ReportBlessedBySeqNum *sync.Map
NextSeqNumToCommit *atomic.Uint64
@@ -2124,6 +2128,8 @@ func (destCCIP *DestCCIPModule) RemoveAllRateLimitTokens(ctx context.Context) er
return destCCIP.OffRamp.RemoveAllRateLimitTokens(ctx)
}
+var wasReceiverDappDeployed = false
+
// DeployContracts deploys all CCIP contracts specific to the destination chain
func (destCCIP *DestCCIPModule) DeployContracts(
sourceCCIP SourceCCIPModule,
@@ -2244,6 +2250,10 @@ func (destCCIP *DestCCIPModule) DeployContracts(
if err != nil {
return fmt.Errorf("waiting for events on destination contract deployments %w", err)
}
+
+ log.Info().Str("Address", destCCIP.ReceiverDapp.Address()).Msg("Receiver Dapp Deployed")
+
+ wasReceiverDappDeployed = true
} else {
destCCIP.ReceiverDapp, err = contractDeployer.NewReceiverDapp(destCCIP.ReceiverDapp.EthAddress)
if err != nil {
@@ -2706,6 +2716,77 @@ func (destCCIP *DestCCIPModule) AssertSeqNumberExecuted(
}
}
+// AssertMessageContentMatch checks if the content of a received message matches the expected content within a specified timeout.
+// It periodically polls the `MessageReceivedWatcher` for the specified message ID, compares the received content with the expected content,
+// and returns an error if the content does not match or the timeout is exceeded.
+func (destCCIP *DestCCIPModule) AssertMessageContentMatch(
+ lggr *zerolog.Logger,
+ messageID string,
+ expectedContent []byte,
+ timeout time.Duration,
+ reqStat *testreporters.RequestStat,
+) error {
+ lggr.Info().
+ Str("MsgID", fmt.Sprintf("0x%x", messageID)).
+ Str("Timeout", timeout.String()).
+ Msg("Waiting for message content to match")
+ timer := time.NewTimer(timeout)
+ defer timer.Stop()
+ resetTimerCount := 0
+ ticker := time.NewTicker(time.Second)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ // Load the message content from the watcher
+ value, ok := destCCIP.MessageReceivedWatcher.Load(messageID)
+ if !ok {
+ continue
+ }
+
+ receivedContent, ok := value.([]uint8)
+ if !ok {
+ lggr.Warn().
+ Str("MsgID", fmt.Sprintf("0x%x", messageID)).
+ Msg("Invalid content type in MessageReceivedWatcher")
+ return errors.New("invalid content type in MessageReceivedWatcher")
+ }
+
+ // Compare the received content with the expected content
+ if string(receivedContent) == string(expectedContent) {
+ lggr.Info().
+ Str("MessageID 0x%x", messageID).
+ Str("Received Content", string(receivedContent)).
+ Str("Expected Content", string(expectedContent)).
+ Msg("Message received and its content matches the sent content")
+ return nil
+ }
+
+ lggr.Warn().
+ Str("MessageID 0x%x", messageID).
+ Str("Received Content", string(receivedContent)).
+ Str("Expected Content", string(expectedContent)).
+ Msg("Message content mismatch")
+
+ return fmt.Errorf("message content did not match for MessageID 0x%x", messageID)
+
+ case <-timer.C:
+ // Handle timeout with potential connection issue recovery
+ if destCCIP.Common.IsConnectionRestoredRecently != nil && !destCCIP.Common.IsConnectionRestoredRecently.Load() {
+ if resetTimerCount > 2 {
+ return fmt.Errorf("possible RPC issue - message content did not match for MessageID 0x%x", messageID)
+ }
+ timer.Reset(timeout)
+ resetTimerCount++
+ lggr.Info().Int("count of reset", resetTimerCount).Msg("Resetting timer to validate message content match")
+ continue
+ }
+
+ return fmt.Errorf("timeout - message was not received for MessageID 0x%x", messageID)
+ }
+ }
+}
+
func DefaultDestinationCCIPModule(
logger *zerolog.Logger,
testConf *testconfig.CCIPTestGroupConfig,
@@ -2735,6 +2816,7 @@ func DefaultDestinationCCIPModule(
ReportBlessedBySeqNum: &sync.Map{},
ExecStateChangedWatcher: &sync.Map{},
ReportAcceptedWatcher: &sync.Map{},
+ MessageReceivedWatcher: &sync.Map{},
}, nil
}
@@ -2743,6 +2825,7 @@ type CCIPRequest struct {
txHash string
txConfirmationTimestamp time.Time
RequestStat *testreporters.RequestStat
+ MessageData []byte
}
func CCIPRequestFromTxHash(txHash common.Hash, chainClient blockchain.EVMClient) (CCIPRequest, *types.Receipt, error) {
@@ -2895,7 +2978,7 @@ func (lane *CCIPLane) RecordStateBeforeTransfer() {
lane.SentReqs = make(map[common.Hash][]CCIPRequest)
}
-func (lane *CCIPLane) AddToSentReqs(txHash common.Hash, reqStats []*testreporters.RequestStat) (*types.Receipt, error) {
+func (lane *CCIPLane) AddToSentReqs(txHash common.Hash, reqStats []*testreporters.RequestStat, msgData []byte) (*types.Receipt, error) {
request, rcpt, err := CCIPRequestFromTxHash(txHash, lane.Source.Common.ChainClient)
if err != nil {
for _, stat := range reqStats {
@@ -2910,6 +2993,7 @@ func (lane *CCIPLane) AddToSentReqs(txHash common.Hash, reqStats []*testreporter
txHash: rcpt.TxHash.Hex(),
txConfirmationTimestamp: request.txConfirmationTimestamp,
RequestStat: stat,
+ MessageData: msgData,
})
lane.NumberOfReq++
}
@@ -2996,7 +3080,7 @@ func (lane *CCIPLane) Multicall(noOfRequests int, multiSendAddr common.Address)
}
return fmt.Errorf("failed to send the multicall: %w", err)
}
- rcpt, err := lane.AddToSentReqs(tx.Hash(), reqStats)
+ rcpt, err := lane.AddToSentReqs(tx.Hash(), reqStats, nil)
if err != nil {
return err
}
@@ -3018,7 +3102,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, msgData, 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)
@@ -3035,7 +3119,7 @@ func (lane *CCIPLane) SendRequests(noOfRequests int, gasLimit *big.Int) error {
noOfTokens++
}
}
- _, err = lane.AddToSentReqs(txHash, []*testreporters.RequestStat{stat})
+ _, err = lane.AddToSentReqs(txHash, []*testreporters.RequestStat{stat}, msgData)
if err != nil {
return err
}
@@ -3345,7 +3429,17 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio
if shouldReturn, phaseErr := isPhaseValid(lane.Logger, testreporters.ExecStateChanged, opts, err); shouldReturn {
return phaseErr
}
+
+ if wasReceiverDappDeployed && lane.SentReqs[txHash][0].MessageData != nil {
+ err = lane.Dest.AssertMessageContentMatch(lane.Logger, string(msgLog.MessageId[:]), lane.SentReqs[txHash][0].MessageData, timeout, reqStat)
+ if err != nil {
+ return errors.Wrap(err, "message validation failed")
+ }
+
+ log.Info().Msg("Message content validation successful")
+ }
}
+
if opts.expectAnyPhaseToFail {
return errors.New("expected at least any one phase to fail but no phase got failed")
}
@@ -3550,6 +3644,35 @@ func (lane *CCIPLane) StartEventWatchers() error {
}
}(reportAccSub)
+ messageReceivedEvent := make(chan *maybe_revert_message_receiver.MaybeRevertMessageReceiverMessageReceived)
+ messageReceivedSub := event.Resubscribe(DefaultResubscriptionTimeout, func(_ context.Context) (event.Subscription, error) {
+ sub, err := lane.Dest.ReceiverDapp.WatchMessageReceived(nil, messageReceivedEvent)
+ if err != nil {
+ log.Error().Err(err).Msg("error in subscribing to message received event")
+ }
+ return sub, err
+ })
+ if messageReceivedSub == nil {
+ return errors.New("failed to subscribe to message received event")
+ }
+ go func(sub event.Subscription) {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case e := <-messageReceivedEvent:
+ messageID := string(e.MessageId[:])
+ messageContent := e.Data
+ messageSender := string(e.Sender)
+ log.Info().Msgf("Message event received for message id: 0x%x", messageID)
+ log.Info().Msgf("Message event received with content: %+v", string(messageContent))
+ log.Info().Msgf("Message event received with sender: 0x%x", messageSender[len(messageSender)-20:])
+ lane.Dest.MessageReceivedWatcher.Store(messageID, messageContent)
+ case <-lane.Context.Done():
+ return
+ }
+ }
+ }(messageReceivedSub)
+
if lane.Dest.Common.ARM != nil {
reportBlessedEvent := make(chan *rmn_contract.RMNContractTaggedRootBlessed)
blessedSub := event.Resubscribe(DefaultResubscriptionTimeout, func(_ context.Context) (event.Subscription, error) {
diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go
index f564ab6244c..13525422bed 100644
--- a/integration-tests/ccip-tests/contracts/contract_deployer.go
+++ b/integration-tests/ccip-tests/contracts/contract_deployer.go
@@ -48,12 +48,12 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool_1_4_0"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool_1_4_0"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/mock_v3_aggregator_contract"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/type_and_version"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers"
ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers"
diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go
index 01245daa966..9ed310c3379 100644
--- a/integration-tests/ccip-tests/contracts/contract_models.go
+++ b/integration-tests/ccip-tests/contracts/contract_models.go
@@ -1104,6 +1104,19 @@ func (rDapp *ReceiverDapp) ToggleRevert(revert bool) error {
return rDapp.client.ProcessTransaction(tx)
}
+// WatchMessageReceived watches for `MessageReceived` events from the ReceiverDapp contract.
+func (rDapp *ReceiverDapp) WatchMessageReceived(opts *bind.WatchOpts, messageReceivedEvent chan *maybe_revert_message_receiver.MaybeRevertMessageReceiverMessageReceived) (event.Subscription, error) {
+ if rDapp.instance != nil {
+ return rDapp.instance.WatchMessageReceived(opts, messageReceivedEvent)
+ }
+
+ newInstance, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(rDapp.EthAddress, wrappers.MustNewWrappedContractBackend(rDapp.client, nil))
+ if err != nil {
+ return nil, fmt.Errorf("failed to create a new ReceiverDapp contract instance: %w", err)
+ }
+ return newInstance.WatchMessageReceived(opts, messageReceivedEvent)
+}
+
type InternalTimestampedPackedUint224 struct {
Value *big.Int
Timestamp uint32
diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go
index f89aadc2483..47e379809af 100644
--- a/integration-tests/ccip-tests/load/helper.go
+++ b/integration-tests/ccip-tests/load/helper.go
@@ -206,7 +206,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))
+ 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 {
diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go
index 344b920f852..e52fd993c34 100644
--- a/integration-tests/ccip-tests/smoke/ccip_test.go
+++ b/integration-tests/ccip-tests/smoke/ccip_test.go
@@ -250,7 +250,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(
+ failedTx, _, _, _, err := tc.lane.Source.SendRequest(
tc.lane.Dest.ReceiverDapp.EthAddress,
big.NewInt(actions.DefaultDestinationGasLimit),
)
@@ -278,7 +278,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))
+ 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())
@@ -342,7 +342,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))
+ 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)
@@ -374,7 +374,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)
@@ -508,7 +508,7 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) {
src.TransferAmount[bpsTokenIndex] = big.NewInt(0)
src.TransferAmount[aggRateTokenIndex] = overCapacityAmount
src.TransferAmount[bpsAndAggTokenIndex] = big.NewInt(0)
- 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.Error(t, err, "Limited token transfer should immediately revert")
errReason, _, err := src.Common.ChainClient.RevertReasonFromTx(failedTx, evm_2_evm_onramp.EVM2EVMOnRampABI)
require.NoError(t, err)
@@ -520,7 +520,7 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) {
src.TransferAmount[aggRateTokenIndex] = big.NewInt(0)
src.TransferAmount[bpsAndAggTokenIndex] = overCapacityAmount
- 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.Error(t, err, "Limited token transfer should immediately revert")
errReason, _, err = src.Common.ChainClient.RevertReasonFromTx(failedTx, evm_2_evm_onramp.EVM2EVMOnRampABI)
require.NoError(t, err)
@@ -568,7 +568,7 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) {
src.TransferAmount[bpsTokenIndex] = big.NewInt(0)
src.TransferAmount[aggRateTokenIndex] = capacityLimit
src.TransferAmount[bpsAndAggTokenIndex] = big.NewInt(0)
- 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.Error(t, err, "Aggregate rate limited token transfer should immediately revert")
errReason, _, err = src.Common.ChainClient.RevertReasonFromTx(failedTx, evm_2_evm_onramp.EVM2EVMOnRampABI)
require.NoError(t, err)
@@ -580,7 +580,7 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) {
src.TransferAmount[aggRateTokenIndex] = big.NewInt(0)
src.TransferAmount[bpsAndAggTokenIndex] = capacityLimit
- 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.Error(t, err, "Aggregate rate limited token transfer should immediately revert")
errReason, _, err = src.Common.ChainClient.RevertReasonFromTx(failedTx, evm_2_evm_onramp.EVM2EVMOnRampABI)
require.NoError(t, err)
@@ -701,7 +701,7 @@ func TestSmokeCCIPTokenPoolRateLimits(t *testing.T) {
// Send limited token over capacity and ensure it fails
src.TransferAmount[freeTokenIndex] = big.NewInt(0)
src.TransferAmount[limitedTokenIndex] = overCapacityAmount
- 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.Error(t, err, "Limited token transfer should immediately revert")
errReason, _, err := src.Common.ChainClient.RevertReasonFromTx(failedTx, lock_release_token_pool.LockReleaseTokenPoolABI)
require.NoError(t, err)
@@ -732,7 +732,7 @@ func TestSmokeCCIPTokenPoolRateLimits(t *testing.T) {
// Send limited token over rate limit and ensure it fails
src.TransferAmount[freeTokenIndex] = big.NewInt(0)
src.TransferAmount[limitedTokenIndex] = capacityLimit
- 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.Error(t, err, "Limited token transfer should immediately revert")
errReason, _, err = src.Common.ChainClient.RevertReasonFromTx(failedTx, lock_release_token_pool.LockReleaseTokenPoolABI)
require.NoError(t, err)
diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go
index bd7a88cd2e3..043eb4ce06f 100644
--- a/integration-tests/contracts/ethereum_contracts.go
+++ b/integration-tests/contracts/ethereum_contracts.go
@@ -25,7 +25,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/counter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
contractsethereum "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator"
@@ -1481,22 +1481,22 @@ func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times
// EthereumWETHToken represents a WETH address
type EthereumWETHToken struct {
client *seth.Client
- instance *weth9_wrapper.WETH9
+ instance *weth9.WETH9
address common.Address
l zerolog.Logger
}
func DeployWETHTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumWETHToken, error) {
- wethTokenAbi, err := weth9_wrapper.WETH9MetaData.GetAbi()
+ wethTokenAbi, err := weth9.WETH9MetaData.GetAbi()
if err != nil {
return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err)
}
- wethDeploymentData, err := client.DeployContract(client.NewTXOpts(), "WETHToken", *wethTokenAbi, common.FromHex(weth9_wrapper.WETH9MetaData.Bin))
+ wethDeploymentData, err := client.DeployContract(client.NewTXOpts(), "WETHToken", *wethTokenAbi, common.FromHex(weth9.WETH9MetaData.Bin))
if err != nil {
return &EthereumWETHToken{}, fmt.Errorf("WETH token instance deployment failed: %w", err)
}
- wethToken, err := weth9_wrapper.NewWETH9(wethDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client))
+ wethToken, err := weth9.NewWETH9(wethDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client))
if err != nil {
return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %w", err)
}
@@ -1510,15 +1510,15 @@ func DeployWETHTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumWE
}
func LoadWETHTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumWETHToken, error) {
- abi, err := weth9_wrapper.WETH9MetaData.GetAbi()
+ abi, err := weth9.WETH9MetaData.GetAbi()
if err != nil {
return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err)
}
client.ContractStore.AddABI("WETHToken", *abi)
- client.ContractStore.AddBIN("WETHToken", common.FromHex(weth9_wrapper.WETH9MetaData.Bin))
+ client.ContractStore.AddBIN("WETHToken", common.FromHex(weth9.WETH9MetaData.Bin))
- wethToken, err := weth9_wrapper.NewWETH9(address, wrappers.MustNewWrappedContractBackend(nil, client))
+ wethToken, err := weth9.NewWETH9(address, wrappers.MustNewWrappedContractBackend(nil, client))
if err != nil {
return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %w", err)
}
diff --git a/integration-tests/go.mod b/integration-tests/go.mod
index d16dc6279a6..8bd55d32ec5 100644
--- a/integration-tests/go.mod
+++ b/integration-tests/go.mod
@@ -12,8 +12,8 @@ replace github.com/smartcontractkit/chainlink/deployment => ../deployment
// Using a separate `require` here to avoid surrounding line changes
// creating potential merge conflicts.
require (
- github.com/smartcontractkit/chainlink/deployment v0.0.0-20250120230622-566643da09fd
- github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0
+ github.com/smartcontractkit/chainlink/deployment v0.0.0-20250128231431-9279badae2f0
+ github.com/smartcontractkit/chainlink/v2 v2.0.0-20250128231431-9279badae2f0
)
require (
@@ -46,10 +46,10 @@ require (
github.com/segmentio/ksuid v1.0.4
github.com/shopspring/decimal v1.4.0
github.com/slack-go/slack v0.15.0
- github.com/smartcontractkit/chain-selectors v1.0.36
+ github.com/smartcontractkit/chain-selectors v1.0.37
github.com/smartcontractkit/chainlink-automation v0.8.1
- github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847
- github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36
+ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9
+ github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0
github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.7
github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2
@@ -436,10 +436,10 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 // indirect
- github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc // indirect
+ github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 // indirect
github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect
- github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 // indirect
+ github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a // indirect
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b // indirect
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect
github.com/smartcontractkit/chainlink-protos/svr v0.0.0-20250123084029-58cce9b32112 // indirect
@@ -534,7 +534,7 @@ require (
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect
- google.golang.org/protobuf v1.35.1 // indirect
+ google.golang.org/protobuf v1.36.4 // 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
diff --git a/integration-tests/go.sum b/integration-tests/go.sum
index 05dc4c895e4..6ed83e0c547 100644
--- a/integration-tests/go.sum
+++ b/integration-tests/go.sum
@@ -1418,24 +1418,24 @@ github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0
github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY=
-github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0=
-github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 h1:kCcrM/osIQFmHx7ZOxeGIeYAMkSmTxkOXcmqHNlXQXQ=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 h1:+/KEPuWctPObgOoEEBCnli1/H3XnjMdCY3Tn+J32XRM=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b h1:eNsqumP7VVJudA7gEcTKVFofealwbPJRinUw24uEmII=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 h1:w7w42ml8MOxdoyAZ9+og0342UkiH3deRM1V0Pj5JR5g=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4/go.mod h1:wtdAmAUMooLavbrTA7PgHg40lyDlKesxI/RR+5Xcz18=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36 h1:bS51NFGHVjkCy7yu9L2Ss4sBsCW6jpa5GuhRAdWWxzM=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc h1:WZERXv2hTYRA0NpWg79ci/ZZSxucmvkty39iUOV8d7I=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc/go.mod h1:2iGmU7fkVsy21Sw8D+OhtYekHLUlJKHzwePKcxIx3Ac=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 h1:CvDfgWoLoYPapOumE/UZCplfCu5oNmy9BuH+6V6+fJ8=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c=
github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a h1:fVtn9CDfoGF40FeqGwLvp9belfIw7VT3lgQTctFGP5E=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM=
@@ -2214,8 +2214,8 @@ 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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
-google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/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=
diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod
index 4e929297779..b13b2bc9d67 100644
--- a/integration-tests/load/go.mod
+++ b/integration-tests/load/go.mod
@@ -14,9 +14,9 @@ replace github.com/smartcontractkit/chainlink/integration-tests => ../
// Using a separate `require` here to avoid surrounding line changes
// creating potential merge conflicts.
require (
- github.com/smartcontractkit/chainlink/deployment v0.0.0-20250120230622-566643da09fd
- github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212011003-de1a8f5e5b42
- github.com/smartcontractkit/chainlink/v2 v2.0.0-20250113180450-c33ab50ac8c0
+ github.com/smartcontractkit/chainlink/deployment v0.0.0-20250128231431-9279badae2f0
+ github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20250128231431-9279badae2f0
+ github.com/smartcontractkit/chainlink/v2 v2.0.0-20250128231431-9279badae2f0
)
require (
@@ -27,9 +27,9 @@ require (
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0
github.com/slack-go/slack v0.15.0
- github.com/smartcontractkit/chain-selectors v1.0.36
- github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847
- github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36
+ github.com/smartcontractkit/chain-selectors v1.0.37
+ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9
+ github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.21
github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.10
github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2
@@ -420,10 +420,10 @@ require (
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect
github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b // indirect
- github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 // indirect
- github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 // indirect
+ github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc // indirect
+ github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 // indirect
github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect
- github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 // indirect
+ github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a // indirect
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b // indirect
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect
github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect
@@ -531,7 +531,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect
google.golang.org/grpc v1.67.1 // indirect
- google.golang.org/protobuf v1.35.1 // indirect
+ google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/guregu/null.v4 v4.0.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum
index e8bef22eab3..1b45a2f89ec 100644
--- a/integration-tests/load/go.sum
+++ b/integration-tests/load/go.sum
@@ -1405,24 +1405,24 @@ github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0
github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8=
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY=
-github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0=
-github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
+github.com/smartcontractkit/chain-selectors v1.0.37 h1:EKVl8wayhOVfnlqfVmEyZ8rXOsnihthONvOPfEOfvbI=
+github.com/smartcontractkit/chain-selectors v1.0.37/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8=
github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU=
github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847 h1:kCcrM/osIQFmHx7ZOxeGIeYAMkSmTxkOXcmqHNlXQXQ=
-github.com/smartcontractkit/chainlink-ccip v0.0.0-20250128193522-bdbfcc588847/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9 h1:+/KEPuWctPObgOoEEBCnli1/H3XnjMdCY3Tn+J32XRM=
+github.com/smartcontractkit/chainlink-ccip v0.0.0-20250203130001-13e2609047e9/go.mod h1:UEnHaxkUsfreeA7rR45LMmua1Uen95tOFUR8/AI9BAo=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b h1:eNsqumP7VVJudA7gEcTKVFofealwbPJRinUw24uEmII=
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250130162116-1b2ee24da54b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36 h1:dytZPggag6auyzmbhpIDmkHu7KrflIBEhLLec4/xFIk=
-github.com/smartcontractkit/chainlink-common v0.4.2-0.20250127125541-a8fa42cc0f36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4 h1:w7w42ml8MOxdoyAZ9+og0342UkiH3deRM1V0Pj5JR5g=
-github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250121210000-2a9675d7a1b4/go.mod h1:wtdAmAUMooLavbrTA7PgHg40lyDlKesxI/RR+5Xcz18=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3 h1:GcPYNVFYjB065CNq0h8nK/VeU08nUkHgBX0cJIEpuHY=
-github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250115135646-ac859d85e7e3/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36 h1:bS51NFGHVjkCy7yu9L2Ss4sBsCW6jpa5GuhRAdWWxzM=
+github.com/smartcontractkit/chainlink-common v0.4.2-0.20250130202959-6f1f48342e36/go.mod h1:Z2e1ynSJ4pg83b4Qldbmryc5lmnrI3ojOdg1FUloa68=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc h1:WZERXv2hTYRA0NpWg79ci/ZZSxucmvkty39iUOV8d7I=
+github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20250130125138-3df261e09ddc/go.mod h1:2iGmU7fkVsy21Sw8D+OhtYekHLUlJKHzwePKcxIx3Ac=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5 h1:CvDfgWoLoYPapOumE/UZCplfCu5oNmy9BuH+6V6+fJ8=
+github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250128203428-08031923fbe5/go.mod h1:pDZagSGjs9U+l4YIFhveDznMHqxuuz+5vRxvVgpbdr8=
github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c=
github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92 h1:lJi0dWfgNJl4Um5KzeZZPVBi//CPDfzzeVmv4Z2OGNY=
-github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250121195549-294ec6a40b92/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a h1:fVtn9CDfoGF40FeqGwLvp9belfIw7VT3lgQTctFGP5E=
+github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250203160922-fbdf168bb92a/go.mod h1:tHem58EihQh63kR2LlAOKDAs9Vbghf1dJKZRGy6LG8g=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b h1:TO1pwFeQKDOmv3loFiLJvYhtymuTgQUw9WgtwK1rueg=
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250121205514-f73e2f86c23b/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM=
@@ -2199,8 +2199,8 @@ 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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
-google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/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=
diff --git a/integration-tests/smoke/capabilities/.gitignore b/integration-tests/smoke/capabilities/.gitignore
index 6e48389b4c3..a532a0fe18f 100644
--- a/integration-tests/smoke/capabilities/.gitignore
+++ b/integration-tests/smoke/capabilities/.gitignore
@@ -1,4 +1,8 @@
# CTFv2 cached environment, no point in committing this
*-cache.toml
-# compiled cron capability
-amd64_cron
\ No newline at end of file
+# compiled cron capability, it should be downloaded by the test
+amd64_cron
+# workflow registration artifact, it's created anew every time the workflow is registered
+abcdefgasd.yaml
+# chainlink cli binary, it should be downloaded by the test
+cre_v*
\ No newline at end of file
diff --git a/integration-tests/smoke/capabilities/environment-ci.toml b/integration-tests/smoke/capabilities/environment-ci.toml
index 67e3c7842d0..fc995e42e26 100644
--- a/integration-tests/smoke/capabilities/environment-ci.toml
+++ b/integration-tests/smoke/capabilities/environment-ci.toml
@@ -3,13 +3,25 @@
type = "anvil"
docker_cmd_params = ["-b", "5"]
+[jd]
+ image = "replace-me"
+
[workflow_config]
- use_chainlink_cli = false
- use_existing = true
+ don_id = 1
+ workflow_name = "abcdefgasd"
+ # without 0x prefix!
+ feed_id = "018bfe8840700040000000000000000000000000000000000000000000000000"
+
+ use_cre_cli = true
+ should_compile_new_workflow = false
+
+ [workflow_config.dependencies]
+ capabilities_version = "v1.0.0-alpha"
+ cre_cli_version = "v0.0.2"
- [workflow_config.existing]
+ [workflow_config.compiled_config]
binary_url = "https://gist.githubusercontent.com/Tofel/8a39af5b68c213d2200446c175b5c99e/raw/cb7b2a56b37e333fe0bdce07b79538c4ce332f5f/binary.wasm.br"
- config_url = "https://gist.githubusercontent.com/Tofel/5b9ccb1cc1a5aa68aa08a5b2066d60a7/raw/7dcdda86b9d50d17029614f370fd2acab1e7fb27/config.json3175390991"
+ config_url = "https://gist.githubusercontent.com/Tofel/19c80e6297914a79449f916e5e65dfdd/raw/1344c259ef7e970dbabaa1e9e885845b8eba5da9/config.json3674692696"
[nodeset]
nodes = 5
diff --git a/integration-tests/smoke/capabilities/environment.toml b/integration-tests/smoke/capabilities/environment.toml
index 11d3784f50c..4fe561ca1b5 100644
--- a/integration-tests/smoke/capabilities/environment.toml
+++ b/integration-tests/smoke/capabilities/environment.toml
@@ -3,16 +3,27 @@
type = "anvil"
docker_cmd_params = ["-b", "5"]
+[jd]
+ # change to your version
+ image = "jd-test-1:latest"
+
[workflow_config]
- use_chainlink_cli = true
- use_existing = true
+ don_id = 1
+ workflow_name = "abcdefgasd"
+ # without 0x prefix!
+ feed_id = "018bfe8840700040000000000000000000000000000000000000000000000000"
- [workflow_config.existing]
- binary_url = "https://gist.githubusercontent.com/Tofel/8a39af5b68c213d2200446c175b5c99e/raw/cb7b2a56b37e333fe0bdce07b79538c4ce332f5f/binary.wasm.br"
- config_url = "https://gist.githubusercontent.com/Tofel/5b9ccb1cc1a5aa68aa08a5b2066d60a7/raw/7dcdda86b9d50d17029614f370fd2acab1e7fb27/config.json3175390991"
+ use_cre_cli = true
+ should_compile_new_workflow = false
+ workflow_folder_location = "path-to-folder-with-main.go-of-your-workflow"
- [workflow_config.chainlink_cli]
- folder_location = "path-to-folder-with-main.go-of-your-workflow"
+ [workflow_config.dependencies]
+ capabilities_version = "v1.0.0-alpha"
+ cre_cli_version = "v0.0.2"
+
+ [workflow_config.compiled_config]
+ binary_url = "https://gist.githubusercontent.com/Tofel/8a39af5b68c213d2200446c175b5c99e/raw/cb7b2a56b37e333fe0bdce07b79538c4ce332f5f/binary.wasm.br"
+ config_url = "https://gist.githubusercontent.com/Tofel/19c80e6297914a79449f916e5e65dfdd/raw/1344c259ef7e970dbabaa1e9e885845b8eba5da9/config.json3674692696"
[nodeset]
nodes = 5
diff --git a/integration-tests/smoke/capabilities/guidelines.md b/integration-tests/smoke/capabilities/guidelines.md
new file mode 100644
index 00000000000..fe1b992309d
--- /dev/null
+++ b/integration-tests/smoke/capabilities/guidelines.md
@@ -0,0 +1,217 @@
+# Test Modification and Execution Guide
+
+## Table of Contents
+1. [How to Run the Test](#how-to-run-the-test)
+2. [Adding a New Capability](#adding-a-new-capability)
+ - [Copying the Binary to the Container](#copying-the-binary-to-the-container)
+ - [Registering the Capability in the Registry Contract](#registering-the-capability-in-the-registry-contract)
+ - [Creating a New Capability Job](#creating-a-new-capability-job)
+3. [Using a New Workflow](#using-a-new-workflow)
+ - [Test Uploads the Binary](#test-uploads-the-binary)
+ - [Workflow Configuration](#workflow-configuration)
+ - [Workflow Secrets](#workflow-secrets)
+ - [Manual Upload of the Binary](#manual-upload-of-the-binary)
+4. [Deployer Address or Deployment Sequence Changes](#deployer-address-or-deployment-sequence-changes)
+5. [Multiple DONs](#multiple-dons)
+6. [Using a Specific Docker Image for Chainlink Node](#using-a-specific-docker-image-for-chainlink-node)
+
+---
+
+## How to Run the Test
+
+The test requires several environment variables. Below is a launch configuration that can be used with the VCS:
+
+```json
+{
+ "name": "Launch Capability Test",
+ "type": "go",
+ "request": "launch",
+ "mode": "test",
+ "program": "${workspaceFolder}/integration-tests/smoke/capabilities",
+ "env": {
+ "CTF_CONFIGS": "environment.toml",
+ "PRIVATE_KEY": "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
+ "GITHUB_GIST_API_TOKEN": "your-gist-read:write-fpat-token",
+ "GITHUB_CAP_API_TOKEN": "your-capabilities-repo-content-read-fpat-token"
+ },
+ "args": [
+ "-test.run",
+ "TestKeystoneWithOCR3Workflow"
+ ]
+}
+```
+
+- **`GITHUB_READ_TOKEN`**: Required for downloading the `cron` capability binary and CRE CLI (if enabled). Requires `content:read` permission for `smartcontractkit/capabilities` and `smartcontractkit/dev-platform` repositories. Use a fine-grained personal access token (PAT) tied to the **organization’s GitHub account**.
+- **`GIST_WRITE_TOKEN`**: Required only for compiling and uploading a new workflow. It needs `gist:read:write` permissions and should be a fine-grained PAT **tied to your personal GitHub account**.
+
+Test also expects you to have the Job Distributor image available locally. By default, `environment.toml` expects image tagged as `jd-test-1:latest`. The easiest way to get it, is to clone the Job Distributor repository and build it locally with:
+```bash
+docker build -t jd-test-1 -f e2e/Dockerfile.e2e
+```
+
+Alternatively, if you have access to the Docker image repository where it's stored you can modify `environment.toml` with the name of the image stored there.
+
+---
+
+## Adding a New Capability
+
+To use a new capability in the test, follow these three steps:
+
+1. Copy the capability binary to the Chainlink node’s Docker container (must be in `linux/amd64` format).
+2. Register the capability in the capability registry contract.
+3. Create a new job on each worker node to launch the capability.
+
+Only after completing these steps can you run a workflow that requires the new capability.
+
+### Copying the Binary to the Container
+
+The test configuration is defined in a TOML file (`environment.toml`), which specifies properties for the Chainlink nodes. The `capabilities` property determines which binaries are copied to the container:
+
+```toml
+ [[nodeset.node_specs]]
+
+ [nodeset.node_specs.node]
+ capabilities = ["./amd64_cron"]
+```
+
+This instructs the framework to copy `./amd64_cron` to the container’s `/home/capabilities/` directory, making it available as `/home/capabilities/amd64_cron`.
+
+> **Note:** While copying the binary to the bootstrap node causes no harm, it is unnecessary since the bootstrap node does not handle capability-related tasks.
+
+### Registering the Capability in the Registry Contract
+
+Next, register the new capability in the **capabilities registry contract** to make it accessible to the workflow DON.
+
+Example definition for a cron capability:
+
+```go
+{
+ LabelledName: "cron-trigger",
+ Version: "1.0.0",
+ CapabilityType: uint8(0), // trigger
+}
+```
+
+Some capabilities may also require `ResponseType` or `ConfigurationContract`. Check with the capability author for the necessary values and ensure the correct capability type is set.
+
+Since this test's code is a living creature we do not indicate any line numbers or functions names. It's advised that you search for the example used above or usages of `CapabilitiesRegistryCapability` type.
+
+### Creating a New Capability Job
+
+Now that worker nodes have access to the binary and it is registered in the contract, create a capability job for each worker node.
+
+Example cron capability job:
+
+```toml
+type = "standardcapabilities"
+schemaVersion = 1
+name = "cron-capabilities"
+forwardingAllowed = false
+command = "/home/capabilities/amd64_cron"
+config = ""
+```
+
+Since this is **not** a built-in capability, you must specify the binary’s path inside the Docker container.
+
+Also, remember that the exact content of the job is hard to know beforehand and you should work with the capability creator to figure out what exactly is required.
+
+---
+
+## Using a New Workflow
+
+To test a new workflow, you have two options:
+
+1. Compile the workflow to a WASM binary and upload it to Gist inside the test.
+2. Manually upload the binary and specify the workflow URL in the test configuration.
+
+### Test Uploads the Binary
+
+For the test to compile and upload the binary, modify your TOML configuration:
+
+```toml
+[workflow_config]
+ use_cre_cli = true
+ should_compile_new_workflow = true
+ workflow_folder_location = "path-to-folder-with-main.go-of-your-workflow"
+```
+
+### Workflow Configuration
+
+If your workflow requires configuration, modify the test to create and pass the configuration data to CRE CLI:
+
+```go
+configFile, err := os.CreateTemp("", "config.json")
+require.NoError(t, err, "failed to create workflow config file")
+
+workflowConfig := PoRWorkflowConfig{
+ FeedID: feedID,
+ URL: "https://api.real-time-reserves.verinumus.io/v1/chainlink/proof-of-reserves/TrueUSD",
+ ConsumerAddress: feedsConsumerAddress.Hex(),
+}
+```
+
+> **Note:** If the workflow is **not configurable**, do not pass configuration data. Instead, pass an empty `[]byte` when compiling or registering it.
+
+### Workflow Secrets
+Currently, workflow secrets are **not supported**.
+
+### Manual Upload of the Binary
+
+If you compiled and uploaded the binary yourself, set the following in your configuration:
+
+```toml
+[workflow_config]
+ use_cre_cli = true
+ should_compile_new_workflow = false
+
+ [workflow_config.compiled_config]
+ binary_url = ""
+ config_url = ""
+```
+
+Both URLs must be accessible by the bootstrap node.
+
+---
+
+## Deployer Address or Deployment Sequence Changes
+
+By default, the test reuses an existing workflow and configuration. The feed consumer address remains the same **as long as the deployer address (`f39fd6e51aad88f6f4ce6ab8827279cfffb92266`) and contract deployment sequence do not change**.
+
+If the deployer private key or deployment sequence changes, run the test in **upload mode**:
+
+```toml
+[workflow_config]
+ use_cre_cli = true
+ should_compile_new_workflow = true
+ workflow_folder_location = "path-to-folder-with-main.go-of-your-workflow"
+```
+
+---
+
+## Multiple DONs
+
+Multiple DONs are **not supported**. A single DON serves as both the **workflow** and **capabilities DON**.
+
+---
+
+## Using a Specific Docker Image for Chainlink Node
+
+By default, the test builds a Docker image from the current branch:
+
+```toml
+[[nodeset.node_specs]]
+ [nodeset.node_specs.node]
+ docker_ctx = "../../.."
+ docker_file = "plugins/chainlink.Dockerfile"
+```
+
+To use an existing image, change it to:
+
+```toml
+[[nodeset.node_specs]]
+ [nodeset.node_specs.node]
+ image = "image-you-want-to-use"
+```
+
+Apply this change to **all node entries** in the test configuration.
+
diff --git a/integration-tests/smoke/capabilities/workflow_test.go b/integration-tests/smoke/capabilities/workflow_test.go
index 3a9035103ad..eb54875eafe 100644
--- a/integration-tests/smoke/capabilities/workflow_test.go
+++ b/integration-tests/smoke/capabilities/workflow_test.go
@@ -1,23 +1,24 @@
package capabilities_test
import (
+ "bufio"
"bytes"
- "cmp"
"context"
"crypto/sha256"
"encoding/base64"
- "encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"io"
- "math"
"math/big"
"net/http"
+ "net/url"
"os"
"os/exec"
+ "path/filepath"
"regexp"
- "slices"
+ "runtime"
+ "strconv"
"strings"
"sync"
"testing"
@@ -26,317 +27,138 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/go-yaml/yaml"
"github.com/google/go-github/v41/github"
+ "github.com/google/uuid"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
+ "google.golang.org/grpc/credentials/insecure"
- "github.com/smartcontractkit/libocr/offchainreporting2/confighelper"
- "github.com/smartcontractkit/libocr/offchainreporting2/types"
- "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper"
- ragetypes "github.com/smartcontractkit/libocr/ragep2p/types"
-
- geth_types "github.com/ethereum/go-ethereum/core/types"
chainselectors "github.com/smartcontractkit/chain-selectors"
"github.com/smartcontractkit/chainlink-testing-framework/framework"
"github.com/smartcontractkit/chainlink-testing-framework/framework/clclient"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework/components/jd"
ns "github.com/smartcontractkit/chainlink-testing-framework/framework/components/simple_node_set"
- "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/ptr"
"github.com/smartcontractkit/chainlink-testing-framework/seth"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows"
- cr_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry"
+ jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder"
- ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/logger"
+ capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb"
ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config"
+ "github.com/smartcontractkit/chainlink/deployment/environment/devenv"
+ "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient"
keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset"
workflow_registry_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry"
+ kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0"
)
-// Copying this to avoid dependency on the core repo
-func GetChainType(chainType string) (uint8, error) {
- switch chainType {
- 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", chainType)
- }
-}
-
-// Copying this to avoid dependency on the core repo
-func MarshalMultichainPublicKey(ost map[string]types.OnchainPublicKey) (types.OnchainPublicKey, error) {
- pubKeys := make([][]byte, 0, len(ost))
- for k, pubKey := range ost {
- typ, err := GetChainType(k)
- 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, errors.New("pubKey doesn't fit into uint16")
- }
- if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil {
- 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
+type WorkflowConfig struct {
+ UseCRECLI bool `toml:"use_cre_cli"`
+ ShouldCompileNewWorkflow bool `toml:"should_compile_new_workflow"`
+ // Tells the test where the workflow to compile is located
+ WorkflowFolderLocation *string `toml:"workflow_folder_location"`
+ CompiledWorkflowConfig *CompiledConfig `toml:"compiled_config"`
+ DependenciesConfig *DependenciesConfig `toml:"dependencies"`
+ // id, which will be used, when registering the DON with the workflow registry,
+ // and when instructing the Gateway job on the bootstrap node as to which workflow to run.
+ DonID uint32 `toml:"don_id" validate:"required"`
+ WorkflowName string `toml:"workflow_name" validate:"required" `
+ FeedID string `toml:"feed_id" validate:"required"`
}
-type WorkflowConfig struct {
- UseChainlinkCLI bool `toml:"use_chainlink_cli"`
- ChainlinkCLI *ChainlinkCLIConfig `toml:"chainlink_cli"`
- UseExising bool `toml:"use_existing"`
- Existing *ExistingWorkflowConfig `toml:"existing"`
+// Defines relases/versions of test dependencies that will be downloaded from Github
+type DependenciesConfig struct {
+ CapabiltiesVersion string `toml:"capabilities_version"`
+ CRECLIVersion string `toml:"cre_cli_version"`
}
-type ExistingWorkflowConfig struct {
+// Defines the location of already compiled workflow binary and config files
+// They will be used if WorkflowConfig.ShouldCompileNewWorkflow is `false`
+// Otherwise test will compile and upload a new workflow
+type CompiledConfig struct {
BinaryURL string `toml:"binary_url"`
ConfigURL string `toml:"config_url"`
}
-type ChainlinkCLIConfig struct {
- FolderLocation *string `toml:"folder_location"`
-}
-
type WorkflowTestConfig struct {
BlockchainA *blockchain.Input `toml:"blockchain_a" validate:"required"`
NodeSet *ns.Input `toml:"nodeset" validate:"required"`
WorkflowConfig *WorkflowConfig `toml:"workflow_config" validate:"required"`
+ JD *jd.Input `toml:"jd" validate:"required"`
}
-type OCR3Config struct {
- Signers [][]byte
- Transmitters []common.Address
- F uint8
- OnchainConfig []byte
- OffchainConfigVersion uint64
- OffchainConfig []byte
-}
-
-type NodeInfo struct {
- OcrKeyBundleID string
- TransmitterAddress string
- PeerID string
- Signer common.Address
- OffchainPublicKey [32]byte
- OnchainPublicKey types.OnchainPublicKey
- ConfigEncryptionPublicKey [32]byte
-}
-
-func extractKey(value string) string {
- parts := strings.Split(value, "_")
- if len(parts) > 1 {
- return parts[len(parts)-1]
- }
- return value
-}
-
-func downloadGHAssetFromLatestRelease(owner, repository, releaseType, assetName, ghToken string) ([]byte, error) {
+func downloadGHAssetFromRelease(owner, repository, releaseTag, assetName, ghToken string) ([]byte, error) {
var content []byte
if ghToken == "" {
return content, errors.New("no github token provided")
}
- if (releaseType == test_env.AUTOMATIC_LATEST_TAG) || (releaseType == test_env.AUTOMATIC_STABLE_LATEST_TAG) {
- ctx := context.Background()
- ts := oauth2.StaticTokenSource(
- &oauth2.Token{AccessToken: ghToken},
- )
- tc := oauth2.NewClient(ctx, ts)
-
- ghClient := github.NewClient(tc)
-
- latestTags, _, err := ghClient.Repositories.ListReleases(context.Background(), owner, repository, &github.ListOptions{PerPage: 20})
- if err != nil {
- return content, errors.Wrapf(err, "failed to list releases for %s", repository)
- }
+ // assuming 180s is enough to fetch releases, find the asset we need and download it
+ // some assets might be 30+ MB, so we need to give it some time (for really slow connections)
+ ctx, cancelFn := context.WithTimeout(context.Background(), 180*time.Second)
+ defer cancelFn()
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: ghToken},
+ )
+ tc := oauth2.NewClient(ctx, ts)
- var latestRelease *github.RepositoryRelease
- for _, tag := range latestTags {
- if releaseType == test_env.AUTOMATIC_STABLE_LATEST_TAG {
- if tag.Prerelease != nil && *tag.Prerelease {
- continue
- }
- if tag.Draft != nil && *tag.Draft {
- continue
- }
- }
- if tag.TagName != nil {
- latestRelease = tag
- break
- }
- }
+ ghClient := github.NewClient(tc)
- if latestRelease == nil {
- return content, errors.New("failed to find latest release with automatic tag: " + releaseType)
- }
+ ghReleases, _, err := ghClient.Repositories.ListReleases(ctx, owner, repository, &github.ListOptions{PerPage: 20})
+ if err != nil {
+ return content, errors.Wrapf(err, "failed to list releases for %s", repository)
+ }
- var assetID int64
- for _, asset := range latestRelease.Assets {
- if strings.Contains(asset.GetName(), assetName) {
- assetID = asset.GetID()
- break
- }
+ var ghRelease *github.RepositoryRelease
+ for _, release := range ghReleases {
+ if release.TagName == nil {
+ continue
}
- if assetID == 0 {
- return content, fmt.Errorf("failed to find asset %s for %s", assetName, *latestRelease.TagName)
+ if *release.TagName == releaseTag {
+ ghRelease = release
+ break
}
+ }
- asset, _, err := ghClient.Repositories.DownloadReleaseAsset(context.Background(), owner, repository, assetID, tc)
- if err != nil {
- return content, errors.Wrapf(err, "failed to download asset %s for %s", assetName, *latestRelease.TagName)
- }
+ if ghRelease == nil {
+ return content, errors.New("failed to find release with tag: " + releaseTag)
+ }
- content, err = io.ReadAll(asset)
- if err != nil {
- return content, err
+ var assetID int64
+ for _, asset := range ghRelease.Assets {
+ if strings.Contains(asset.GetName(), assetName) {
+ assetID = asset.GetID()
+ break
}
-
- return content, nil
}
- return content, errors.New("no automatic tag provided")
-}
-
-func getNodesInfo(
- t *testing.T,
- nodes []*clclient.ChainlinkClient,
-) (nodesInfo []NodeInfo) {
- nodesInfo = make([]NodeInfo, len(nodes))
-
- for i, node := range nodes {
- // OCR Keys
- ocr2Keys, err := node.MustReadOCR2Keys()
- require.NoError(t, err)
- nodesInfo[i].OcrKeyBundleID = ocr2Keys.Data[0].ID
-
- firstOCR2Key := ocr2Keys.Data[0].Attributes
- nodesInfo[i].Signer = common.HexToAddress(extractKey(firstOCR2Key.OnChainPublicKey))
-
- pubKeys := make(map[string]types.OnchainPublicKey)
- ethOnchainPubKey, err := hex.DecodeString(extractKey(firstOCR2Key.OnChainPublicKey))
- require.NoError(t, err)
- pubKeys["evm"] = ethOnchainPubKey
-
- multichainPubKey, err := MarshalMultichainPublicKey(pubKeys)
- require.NoError(t, err)
- nodesInfo[i].OnchainPublicKey = multichainPubKey
-
- offchainPublicKeyBytes, err := hex.DecodeString(extractKey(firstOCR2Key.OffChainPublicKey))
- require.NoError(t, err)
- var offchainPublicKey [32]byte
- copy(offchainPublicKey[:], offchainPublicKeyBytes)
- nodesInfo[i].OffchainPublicKey = offchainPublicKey
-
- sharedSecretEncryptionPublicKeyBytes, err := hex.DecodeString(extractKey(firstOCR2Key.ConfigPublicKey))
- require.NoError(t, err)
- var sharedSecretEncryptionPublicKey [32]byte
- copy(sharedSecretEncryptionPublicKey[:], sharedSecretEncryptionPublicKeyBytes)
- nodesInfo[i].ConfigEncryptionPublicKey = sharedSecretEncryptionPublicKey
-
- // ETH Keys
- ethKeys, err := node.MustReadETHKeys()
- require.NoError(t, err)
- nodesInfo[i].TransmitterAddress = ethKeys.Data[0].Attributes.Address
-
- // P2P Keys
- p2pKeys, err := node.MustReadP2PKeys()
- require.NoError(t, err)
- nodesInfo[i].PeerID = p2pKeys.Data[0].Attributes.PeerID
+ if assetID == 0 {
+ return content, fmt.Errorf("failed to find asset %s for %s", assetName, *ghRelease.TagName)
}
- return nodesInfo
-}
-
-func generateOCR3Config(
- t *testing.T,
- nodesInfo []NodeInfo,
-) (config *OCR3Config) {
- oracleIdentities := []confighelper.OracleIdentityExtra{}
- transmissionSchedule := []int{}
-
- for _, nodeInfo := range nodesInfo {
- transmissionSchedule = append(transmissionSchedule, 1)
- oracleIdentity := confighelper.OracleIdentityExtra{}
- oracleIdentity.OffchainPublicKey = nodeInfo.OffchainPublicKey
- oracleIdentity.OnchainPublicKey = nodeInfo.OnchainPublicKey
- oracleIdentity.ConfigEncryptionPublicKey = nodeInfo.ConfigEncryptionPublicKey
- oracleIdentity.PeerID = nodeInfo.PeerID
- oracleIdentity.TransmitAccount = types.Account(nodeInfo.TransmitterAddress)
- oracleIdentities = append(oracleIdentities, oracleIdentity)
- }
-
- maxDurationInitialization := 10 * time.Second
-
- signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests(
- 5*time.Second, // DeltaProgress: Time between rounds
- 5*time.Second, // DeltaResend: Time between resending unconfirmed transmissions
- 5*time.Second, // DeltaInitial: Initial delay before starting the first round
- 2*time.Second, // DeltaRound: Time between rounds within an epoch
- 500*time.Millisecond, // DeltaGrace: Grace period for delayed transmissions
- 1*time.Second, // DeltaCertifiedCommitRequest: Time between certified commit requests
- 30*time.Second, // DeltaStage: Time between stages of the protocol
- uint64(10), // MaxRoundsPerEpoch: Maximum number of rounds per epoch
- transmissionSchedule, // TransmissionSchedule: Transmission schedule
- oracleIdentities, // Oracle identities with their public keys
- nil, // Plugin config (empty for now)
- &maxDurationInitialization, // MaxDurationInitialization: ???
- 1*time.Second, // MaxDurationQuery: Maximum duration for querying
- 1*time.Second, // MaxDurationObservation: Maximum duration for observation
- 1*time.Second, // MaxDurationAccept: Maximum duration for acceptance
- 1*time.Second, // MaxDurationTransmit: Maximum duration for transmission
- 1, // F: Maximum number of faulty oracles
- nil, // OnChain config (empty for now)
- )
- require.NoError(t, err)
-
- signerAddresses := [][]byte{}
- for _, signer := range signers {
- signerAddresses = append(signerAddresses, signer)
+ asset, _, err := ghClient.Repositories.DownloadReleaseAsset(ctx, owner, repository, assetID, tc)
+ if err != nil {
+ return content, errors.Wrapf(err, "failed to download asset %s for %s", assetName, *ghRelease.TagName)
}
- transmitterAddresses := []common.Address{}
- for _, transmitter := range transmitters {
- transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(transmitter)))
+ content, err = io.ReadAll(asset)
+ if err != nil {
+ return content, err
}
- return &OCR3Config{
- Signers: signerAddresses,
- Transmitters: transmitterAddresses,
- F: f,
- OnchainConfig: onchainConfig,
- OffchainConfigVersion: offchainConfigVersion,
- OffchainConfig: offchainConfig,
- }
+ return content, nil
}
func GenerateWorkflowIDFromStrings(owner string, name string, workflow []byte, config []byte, secretsURL string) (string, error) {
@@ -404,7 +226,7 @@ func downloadAndDecode(url string) ([]byte, error) {
return decoded, nil
}
-type ChainlinkCliSettings struct {
+type CRECLISettings struct {
DevPlatform DevPlatform `yaml:"dev-platform"`
UserWorkflow UserWorkflow `yaml:"user-workflow"`
Logging Logging `yaml:"logging"`
@@ -453,49 +275,83 @@ type PoRWorkflowConfig struct {
}
const (
- chainlinkCliAssetFile = "cre_v1.0.2_linux_amd64.tar.gz"
- cronCapabilityAssetFile = "amd64_cron"
+ CRECLISettingsFileName = ".cre-cli-settings.yaml"
+ cronCapabilityAssetFile = "amd64_cron"
+ e2eJobDistributorImageEnvVarName = "E2E_JD_IMAGE"
+ e2eJobDistributorVersionEnvVarName = "E2E_JD_VERSION"
+ ghReadTokenEnvVarName = "GITHUB_READ_TOKEN"
+)
+
+var (
+ CRECLICommand string
)
-func downloadAndInstallChainlinkCLI(ghToken string) error {
- content, err := downloadGHAssetFromLatestRelease("smartcontractkit", "dev-platform", test_env.AUTOMATIC_LATEST_TAG, chainlinkCliAssetFile, ghToken)
+func downloadAndInstallChainlinkCLI(ghToken, version string) error {
+ system := runtime.GOOS
+ arch := runtime.GOARCH
+
+ switch system {
+ case "darwin", "linux":
+ // nothing to do, we have the binaries
+ default:
+ return fmt.Errorf("chainlnk-cli does not support OS: %s", system)
+ }
+
+ switch arch {
+ case "amd64", "arm64":
+ // nothing to do, we have the binaries
+ default:
+ return fmt.Errorf("chainlnk-cli does not support arch: %s", arch)
+ }
+
+ CRECLIAssetFile := fmt.Sprintf("cre_%s_%s_%s.tar.gz", version, system, arch)
+ content, err := downloadGHAssetFromRelease("smartcontractkit", "dev-platform", version, CRECLIAssetFile, ghToken)
if err != nil {
- return err
+ return errors.Wrapf(err, "failed to download CRE CLI asset %s", CRECLIAssetFile)
}
- tmpfile, err := os.CreateTemp("", chainlinkCliAssetFile)
+ tmpfile, err := os.CreateTemp("", CRECLIAssetFile)
if err != nil {
- return err
+ return errors.Wrapf(err, "failed to create temp file for CRE CLI asset %s", CRECLIAssetFile)
}
defer tmpfile.Close()
if _, err := tmpfile.Write(content); err != nil {
- return err
+ return errors.Wrapf(err, "failed to write content to temp file for CRE CLI asset %s", CRECLIAssetFile)
}
- cmd := exec.Command("tar", "-xvf", tmpfile.Name()) // #nosec G204
- err = cmd.Run()
+ cmd := exec.Command("tar", "-xvf", tmpfile.Name(), "-C", ".") // #nosec G204
+ if cmd.Run() != nil {
+ return errors.Wrapf(err, "failed to extract CRE CLI asset %s", CRECLIAssetFile)
+ }
- if err != nil {
- return err
+ extractedFileName := fmt.Sprintf("cre_%s_%s_%s", version, system, arch)
+ cmd = exec.Command("chmod", "+x", extractedFileName)
+ if cmd.Run() != nil {
+ return errors.Wrapf(err, "failed to make %s executable", extractedFileName)
}
- cmd = exec.Command("chmod", "+x", "chainlink-cli")
- err = cmd.Run()
+ // set it to absolute path, because some commands (e.g. compile) need to be executed in the context
+ // of the workflow directory
+ extractedFile, err := os.Open(extractedFileName)
+ if err != nil {
+ return errors.Wrapf(err, "failed to open %s", extractedFileName)
+ }
+ CRECLICommand, err = filepath.Abs(extractedFile.Name())
if err != nil {
- return err
+ return errors.Wrapf(err, "failed to get absolute path for %s", tmpfile.Name())
}
- if isInstalled := isInstalled("chainlink-cli"); !isInstalled {
- return errors.New("failed to install chainlink-cli or it is not available in the PATH")
+ if isInstalled := isInstalled(CRECLICommand); !isInstalled {
+ return errors.New("failed to install CRE CLI or it is not available in the PATH")
}
return nil
}
-func downloadCronCapability(ghToken string) (string, error) {
- content, err := downloadGHAssetFromLatestRelease("smartcontractkit", "capabilities", test_env.AUTOMATIC_LATEST_TAG, cronCapabilityAssetFile, ghToken)
+func downloadCronCapability(ghToken, version string) (string, error) {
+ content, err := downloadGHAssetFromRelease("smartcontractkit", "capabilities", version, cronCapabilityAssetFile, ghToken)
if err != nil {
return "", err
}
@@ -514,97 +370,175 @@ func downloadCronCapability(ghToken string) (string, error) {
return fileName, nil
}
-func validateInputsAndEnvVars(t *testing.T, testConfig *WorkflowTestConfig) {
+func validateInputsAndEnvVars(t *testing.T, in *WorkflowTestConfig) {
require.NotEmpty(t, os.Getenv("PRIVATE_KEY"), "PRIVATE_KEY env var must be set")
- if !testConfig.WorkflowConfig.UseChainlinkCLI {
- require.True(t, testConfig.WorkflowConfig.UseExising, "if you are not using chainlink-cli you must use an existing workflow")
- }
+ require.NotEmpty(t, in.WorkflowConfig.DependenciesConfig, "dependencies config must be set")
- ghToken := os.Getenv("GITHUB_API_TOKEN")
- _, err := downloadCronCapability(ghToken)
- require.NoError(t, err, "failed to download cron capability. Make sure token has content:read permissions to the capabilities repo")
+ if !in.WorkflowConfig.UseCRECLI {
+ require.False(t, in.WorkflowConfig.ShouldCompileNewWorkflow, "if you are not using CRE CLI you cannot compile a new workflow")
+ }
- // TODO this part should ideally happen outside of the test, but due to how our reusable e2e test workflow is structured now
- // we cannot execute this part in workflow steps (it doesn't support any pre-execution hooks)
+ var ghReadToken string
+ // this is a small hack to avoid changing the reusable workflow
if os.Getenv("IS_CI") == "true" {
+ // This part should ideally happen outside of the test, but due to how our reusable e2e test workflow is structured now
+ // we cannot execute this part in workflow steps (it doesn't support any pre-execution hooks)
require.NotEmpty(t, os.Getenv(ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV), "missing env var: "+ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV)
require.NotEmpty(t, os.Getenv(ctfconfig.E2E_TEST_CHAINLINK_VERSION_ENV), "missing env var: "+ctfconfig.E2E_TEST_CHAINLINK_VERSION_ENV)
+ require.NotEmpty(t, os.Getenv(e2eJobDistributorImageEnvVarName), "missing env var: "+e2eJobDistributorImageEnvVarName)
+ require.NotEmpty(t, os.Getenv(e2eJobDistributorVersionEnvVarName), "missing env var: "+e2eJobDistributorVersionEnvVarName)
+
+ // disabled until we can figure out how to generate a gist read:write token in CI
+ /*
+ This test can be run in two modes:
+ 1. `existing` mode: it uses a workflow binary (and configuration) file that is already uploaded to Gist
+ 2. `compile` mode: it compiles a new workflow binary and uploads it to Gist
+
+ For the `new` mode to work, the `GITHUB_API_TOKEN` env var must be set to a token that has `gist:read` and `gist:write` permissions, but this permissions
+ are tied to account not to repository. Currently, we have no service account in the CI at all. And using a token that's tied to personal account of a developer
+ is not a good idea. So, for now, we are only allowing the `existing` mode in CI.
+ */
+ require.False(t, in.WorkflowConfig.ShouldCompileNewWorkflow, "you cannot compile a new workflow in the CI as of now due to issues with generating a gist write token")
+
+ // we use this special function to subsitute a placeholder env variable with the actual environment variable name
+ // it is defined in .github/e2e-tests.yml as '{{ env.GITHUB_API_TOKEN }}'
+ ghReadToken = ctfconfig.MustReadEnvVar_String(ghReadTokenEnvVarName)
+ } else {
+ ghReadToken = os.Getenv(ghReadTokenEnvVarName)
+ }
+
+ require.NotEmpty(t, ghReadToken, ghReadTokenEnvVarName+" env var must be set")
+ require.NotEmpty(t, in.WorkflowConfig.DependenciesConfig.CapabiltiesVersion, "capabilities_version must be set in the dependencies config")
- if testConfig.WorkflowConfig.UseChainlinkCLI {
- err = downloadAndInstallChainlinkCLI(ghToken)
- require.NoError(t, err, "failed to download and install chainlink-cli. Make sure token has content:read permissions to the dev-platform repo")
+ _, err := downloadCronCapability(ghReadToken, in.WorkflowConfig.DependenciesConfig.CapabiltiesVersion)
+ require.NoError(t, err, "failed to download cron capability. Make sure token has content:read permissions to the capabilities repo")
+
+ if in.WorkflowConfig.UseCRECLI {
+ require.NotEmpty(t, in.WorkflowConfig.DependenciesConfig.CRECLIVersion, "chainlink_cli_version must be set in the dependencies config")
+
+ err = downloadAndInstallChainlinkCLI(ghReadToken, in.WorkflowConfig.DependenciesConfig.CRECLIVersion)
+ require.NoError(t, err, "failed to download and install CRE CLI. Make sure token has content:read permissions to the dev-platform repo")
+
+ if in.WorkflowConfig.ShouldCompileNewWorkflow {
+ gistWriteToken := os.Getenv("GIST_WRITE_TOKEN")
+ require.NotEmpty(t, gistWriteToken, "GIST_WRITE_TOKEN must be set to use CRE CLI to compile workflows. It requires gist:read and gist:write permissions")
+ err := os.Setenv("GITHUB_API_TOKEN", gistWriteToken)
+ require.NoError(t, err, "failed to set GITHUB_API_TOKEN env var")
+ require.NotEmpty(t, in.WorkflowConfig.WorkflowFolderLocation, "workflow_folder_location must be set, when compiling new workflow")
}
}
- if testConfig.WorkflowConfig.UseChainlinkCLI {
- require.True(t, isInstalled("chainlink-cli"), "chainlink-cli is required for this test. Please install it, add to path and run again")
+ // make sure the feed id is in the correct format
+ in.WorkflowConfig.FeedID = strings.TrimPrefix(in.WorkflowConfig.FeedID, "0x")
+}
- if !testConfig.WorkflowConfig.UseExising {
- require.NotEmpty(t, os.Getenv("GITHUB_API_TOKEN"), "GITHUB_API_TOKEN must be set to use chainlink-cli. It requires gist:read and gist:write permissions")
+// copied from Bala's unmerged PR: https://github.com/smartcontractkit/chainlink/pull/15751
+// TODO: remove this once the PR is merged and import his function
+func getNodeInfo(nodeOut *ns.Output, bootstrapNodeCount int) ([]devenv.NodeInfo, error) {
+ var nodeInfo []devenv.NodeInfo
+ for i := 1; i <= len(nodeOut.CLNodes); i++ {
+ p2pURL, err := url.Parse(nodeOut.CLNodes[i-1].Node.DockerP2PUrl)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse p2p url: %w", err)
+ }
+ if i <= bootstrapNodeCount {
+ nodeInfo = append(nodeInfo, devenv.NodeInfo{
+ IsBootstrap: true,
+ Name: fmt.Sprintf("bootstrap-%d", i),
+ P2PPort: p2pURL.Port(),
+ CLConfig: nodeclient.ChainlinkConfig{
+ URL: nodeOut.CLNodes[i-1].Node.HostURL,
+ Email: nodeOut.CLNodes[i-1].Node.APIAuthUser,
+ Password: nodeOut.CLNodes[i-1].Node.APIAuthPassword,
+ InternalIP: nodeOut.CLNodes[i-1].Node.InternalIP,
+ },
+ })
} else {
- require.NotEmpty(t, testConfig.WorkflowConfig.ChainlinkCLI.FolderLocation, "folder_location must be set in the chainlink_cli config")
+ nodeInfo = append(nodeInfo, devenv.NodeInfo{
+ IsBootstrap: false,
+ Name: fmt.Sprintf("node-%d", i),
+ P2PPort: p2pURL.Port(),
+ CLConfig: nodeclient.ChainlinkConfig{
+ URL: nodeOut.CLNodes[i-1].Node.HostURL,
+ Email: nodeOut.CLNodes[i-1].Node.APIAuthUser,
+ Password: nodeOut.CLNodes[i-1].Node.APIAuthPassword,
+ InternalIP: nodeOut.CLNodes[i-1].Node.InternalIP,
+ },
+ })
}
}
+ return nodeInfo, nil
}
-func buildChainlinkDeploymentEnv(t *testing.T, sc *seth.Client) (*deployment.Environment, uint64) {
+func buildChainlinkDeploymentEnv(t *testing.T, jdOutput *jd.Output, nodeOutput *ns.Output, bs *blockchain.Output, sc *seth.Client) (*deployment.Environment, *devenv.DON, uint64) {
lgr := logger.TestLogger(t)
- addressBook := deployment.NewMemoryAddressBook()
- chainMap := make(map[uint64]deployment.Chain)
- ctx := context.Background()
-
chainSelector, err := chainselectors.SelectorFromChainId(sc.Cfg.Network.ChainID)
require.NoError(t, err, "failed to get chain selector for chain id %d", sc.Cfg.Network.ChainID)
- chainMap[chainSelector] = deployment.Chain{
- Selector: chainSelector,
- Client: sc.Client,
- DeployerKey: sc.NewTXOpts(seth.WithNonce(nil)), // set nonce to nil, so that it will be fetched from the chain
- Confirm: func(tx *geth_types.Transaction) (uint64, error) {
- decoded, revertErr := sc.DecodeTx(tx)
- if revertErr != nil {
- return 0, revertErr
- }
- if decoded.Receipt == nil {
- return 0, fmt.Errorf("no receipt found for transaction %s even though it wasn't reverted. This should not happen", tx.Hash().String())
- }
- return decoded.Receipt.BlockNumber.Uint64(), nil
+
+ nodeInfo, err := getNodeInfo(nodeOutput, 1)
+ require.NoError(t, err, "failed to get node info")
+
+ jdConfig := devenv.JDConfig{
+ GRPC: jdOutput.HostGRPCUrl,
+ WSRPC: jdOutput.DockerWSRPCUrl,
+ Creds: insecure.NewCredentials(),
+ NodeInfo: nodeInfo,
+ }
+
+ require.GreaterOrEqual(t, len(bs.Nodes), 1, "expected at least one node in the blockchain output")
+
+ devenvConfig := devenv.EnvironmentConfig{
+ JDConfig: jdConfig,
+ Chains: []devenv.ChainConfig{
+ {
+ ChainID: sc.Cfg.Network.ChainID,
+ ChainName: sc.Cfg.Network.Name,
+ ChainType: strings.ToUpper(bs.Family),
+ WSRPCs: []devenv.CribRPCs{{
+ External: bs.Nodes[0].HostWSUrl,
+ Internal: bs.Nodes[0].DockerInternalWSUrl,
+ }},
+ HTTPRPCs: []devenv.CribRPCs{{
+ External: bs.Nodes[0].HostHTTPUrl,
+ Internal: bs.Nodes[0].DockerInternalHTTPUrl,
+ }},
+ DeployerKey: sc.NewTXOpts(seth.WithNonce(nil)), // set nonce to nil, so that it will be fetched from the chain
+ },
},
}
- return deployment.NewEnvironment("ctfV2", lgr, addressBook, chainMap, nil, nil, nil, func() context.Context { return ctx }, deployment.OCRSecrets{}), chainSelector
+ env, don, err := devenv.NewEnvironment(context.Background, lgr, devenvConfig)
+ require.NoError(t, err, "failed to create environment")
+
+ return env, don, chainSelector
}
-func prepareCapabilitiesRegistry(t *testing.T, sc *seth.Client, allCaps []cr_wrapper.CapabilitiesRegistryCapability) (common.Address, [][32]byte) {
- capRegAddr, tx, capabilitiesRegistryInstance, err := cr_wrapper.DeployCapabilitiesRegistry(sc.NewTXOpts(), sc.Client)
- _, decodeErr := sc.Decode(tx, err)
- require.NoError(t, decodeErr, "failed to deploy capabilities registry contract")
+func deployKeystoneContracts(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64) keystone_changeset.ContractSet {
+ // Deploy keystone forwarder contract
+ _ = deployKeystoneForwarder(t, testLogger, ctfEnv, chainSelector)
- _, decodeErr = sc.Decode(capabilitiesRegistryInstance.AddCapabilities(
- sc.NewTXOpts(),
- allCaps,
- ))
- require.NoError(t, decodeErr, "failed to add capabilities to capabilities registry")
-
- hashedCapabilities := make([][32]byte, len(allCaps))
- for i, capability := range allCaps {
- hashed, err := capabilitiesRegistryInstance.GetHashedCapabilityId(
- sc.NewCallOpts(),
- capability.LabelledName,
- capability.Version,
- )
- require.NoError(t, err, "failed to get hashed capability ID for %s", capability.LabelledName)
- hashedCapabilities[i] = hashed
- }
+ // Deploy OCR3 contract
+ _ = deployOCR3(t, testLogger, ctfEnv, chainSelector)
- return capRegAddr, hashedCapabilities
-}
+ // Deploy capabilities registry contract
+ _ = deployCapabilitiesRegistry(t, testLogger, ctfEnv, chainSelector)
-func deployKeystoneForwarder(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64) common.Address {
- output, err := keystone_changeset.DeployForwarder(*ctfEnv, keystone_changeset.DeployForwarderRequest{
- ChainSelectors: []uint64{chainSelector},
+ contractSetResponse, err := keystone_changeset.GetContractSets(nil, &keystone_changeset.GetContractSetsRequest{
+ Chains: ctfEnv.Chains,
+ AddressBook: ctfEnv.ExistingAddresses,
})
- require.NoError(t, err, "failed to deploy forwarder contract")
+ require.NoError(t, err, "failed to get contract sets")
+
+ contractSet, ok := contractSetResponse.ContractSets[chainSelector]
+ require.True(t, ok, "failed to get contract set for chain %d", chainSelector)
+
+ return contractSet
+}
+
+func deployOCR3(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64) common.Address {
+ output, err := keystone_changeset.DeployOCR3(*ctfEnv, chainSelector)
+ require.NoError(t, err, "failed to deploy OCR3 Capability contract")
err = ctfEnv.ExistingAddresses.Merge(output.AddressBook)
require.NoError(t, err, "failed to merge address book")
@@ -614,9 +548,9 @@ func deployKeystoneForwarder(t *testing.T, testLogger zerolog.Logger, ctfEnv *de
var forwarderAddress common.Address
for addrStr, tv := range addresses {
- if strings.Contains(tv.String(), "KeystoneForwarder") {
+ if strings.Contains(tv.String(), "OCR3Capability") {
forwarderAddress = common.HexToAddress(addrStr)
- testLogger.Info().Msgf("Deployed KeystoneForwarder contract at %s", forwarderAddress.Hex())
+ testLogger.Info().Msgf("Deployed OCR3Capability contract at %s", forwarderAddress.Hex())
break
}
}
@@ -624,47 +558,50 @@ func deployKeystoneForwarder(t *testing.T, testLogger zerolog.Logger, ctfEnv *de
return forwarderAddress
}
-func configureKeystoneForwarder(t *testing.T, forwarderAddress common.Address, sc *seth.Client, nodesInfo []NodeInfo) {
- forwarderInstance, err := forwarder.NewKeystoneForwarder(forwarderAddress, sc.Client)
- require.NoError(t, err, "failed to create forwarder instance")
+func deployCapabilitiesRegistry(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64) common.Address {
+ output, err := keystone_changeset.DeployCapabilityRegistry(*ctfEnv, chainSelector)
+ require.NoError(t, err, "failed to deploy Capabilities Registry contract")
- signers := make([]common.Address, len(nodesInfo)-1)
+ err = ctfEnv.ExistingAddresses.Merge(output.AddressBook)
+ require.NoError(t, err, "failed to merge address book")
- for i, node := range nodesInfo {
- // skip the first node, as it's the bootstrap node
- // it doesn't have any capabilities that are required by the workflow
- if i == 0 {
- continue
+ addresses, err := ctfEnv.ExistingAddresses.AddressesForChain(chainSelector)
+ require.NoError(t, err, "failed to get addresses for chain %d from the address book", chainSelector)
+
+ var forwarderAddress common.Address
+ for addrStr, tv := range addresses {
+ if strings.Contains(tv.String(), "CapabilitiesRegistry") {
+ forwarderAddress = common.HexToAddress(addrStr)
+ testLogger.Info().Msgf("Deployed Capabilities Registry contract at %s", forwarderAddress.Hex())
+ break
}
- signers[i-1] = node.Signer
}
- _, err = sc.Decode(forwarderInstance.SetConfig(
- sc.NewTXOpts(),
- 1, // donID
- 1, // configVersion -- wonder what it does
- 1, // maximum number of faulty nodes
- signers))
- require.NoError(t, err, "failed to set config for forwarder")
+ return forwarderAddress
}
-func configureOCR3Capability(t *testing.T, ocr3CapabilityAddress common.Address, sc *seth.Client, nodeInfo []NodeInfo) {
- workflowNodesetInfo := nodeInfo[1:]
+func deployKeystoneForwarder(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64) common.Address {
+ output, err := keystone_changeset.DeployForwarder(*ctfEnv, keystone_changeset.DeployForwarderRequest{
+ ChainSelectors: []uint64{chainSelector},
+ })
+ require.NoError(t, err, "failed to deploy forwarder contract")
- ocr3CapabilityContract, err := ocr3_capability.NewOCR3Capability(ocr3CapabilityAddress, sc.Client)
- require.NoError(t, err, "failed to create OCR3 capability contract instance")
+ err = ctfEnv.ExistingAddresses.Merge(output.AddressBook)
+ require.NoError(t, err, "failed to merge address book")
- ocr3Config := generateOCR3Config(t, workflowNodesetInfo)
- _, decodeErr := sc.Decode(ocr3CapabilityContract.SetConfig(
- sc.NewTXOpts(),
- ocr3Config.Signers,
- ocr3Config.Transmitters,
- ocr3Config.F,
- ocr3Config.OnchainConfig,
- ocr3Config.OffchainConfigVersion,
- ocr3Config.OffchainConfig,
- ))
- require.NoError(t, decodeErr, "failed to set OCR3 configuration")
+ addresses, err := ctfEnv.ExistingAddresses.AddressesForChain(chainSelector)
+ require.NoError(t, err, "failed to get addresses for chain %d from the address book", chainSelector)
+
+ var forwarderAddress common.Address
+ for addrStr, tv := range addresses {
+ if strings.Contains(tv.String(), "KeystoneForwarder") {
+ forwarderAddress = common.HexToAddress(addrStr)
+ testLogger.Info().Msgf("Deployed KeystoneForwarder contract at %s", forwarderAddress.Hex())
+ break
+ }
+ }
+
+ return forwarderAddress
}
func prepareWorkflowRegistry(t *testing.T, testLogger zerolog.Logger, ctfEnv *deployment.Environment, chainSelector uint64, sc *seth.Client, donID uint32) common.Address {
@@ -718,8 +655,8 @@ func prepareFeedsConsumer(t *testing.T, testLogger zerolog.Logger, ctfEnv *deplo
var feedsConsumerAddress common.Address
for addrStr, tv := range addresses {
if strings.Contains(tv.String(), "FeedConsumer") {
- testLogger.Info().Msgf("Deployed FeedConsumer contract at %s", feedsConsumerAddress.Hex())
feedsConsumerAddress = common.HexToAddress(addrStr)
+ testLogger.Info().Msgf("Deployed FeedConsumer contract at %s", feedsConsumerAddress.Hex())
break
}
}
@@ -761,26 +698,14 @@ func prepareFeedsConsumer(t *testing.T, testLogger zerolog.Logger, ctfEnv *deplo
return feedsConsumerAddress
}
-func deployOCR3Capability(t *testing.T, testLogger zerolog.Logger, sc *seth.Client) common.Address {
- ocr3CapabilityAddress, tx, _, err := ocr3_capability.DeployOCR3Capability(
- sc.NewTXOpts(),
- sc.Client,
- )
- _, decodeErr := sc.Decode(tx, err)
- require.NoError(t, decodeErr, "failed to deploy OCR Capability contract")
-
- testLogger.Info().Msgf("Deployed OCR3 Capability contract at %s", ocr3CapabilityAddress.Hex())
-
- return ocr3CapabilityAddress
-}
func registerWorkflowDirectly(t *testing.T, in *WorkflowTestConfig, sc *seth.Client, workflowRegistryAddr common.Address, donID uint32, workflowName string) {
- require.NotEmpty(t, in.WorkflowConfig.Existing.BinaryURL)
- workFlowData, err := downloadAndDecode(in.WorkflowConfig.Existing.BinaryURL)
+ require.NotEmpty(t, in.WorkflowConfig.CompiledWorkflowConfig.BinaryURL)
+ workFlowData, err := downloadAndDecode(in.WorkflowConfig.CompiledWorkflowConfig.BinaryURL)
require.NoError(t, err, "failed to download and decode workflow binary")
var configData []byte
- if in.WorkflowConfig.Existing.ConfigURL != "" {
- configData, err = download(in.WorkflowConfig.Existing.ConfigURL)
+ if in.WorkflowConfig.CompiledWorkflowConfig.ConfigURL != "" {
+ configData, err = download(in.WorkflowConfig.CompiledWorkflowConfig.ConfigURL)
require.NoError(t, err, "failed to download workflow config")
}
@@ -792,19 +717,28 @@ func registerWorkflowDirectly(t *testing.T, in *WorkflowTestConfig, sc *seth.Cli
require.NoError(t, err, "failed to create workflow registry instance")
// use non-encoded workflow name
- _, decodeErr := sc.Decode(workflowRegistryInstance.RegisterWorkflow(sc.NewTXOpts(), workflowName, [32]byte(common.Hex2Bytes(workflowID)), donID, uint8(0), in.WorkflowConfig.Existing.BinaryURL, in.WorkflowConfig.Existing.ConfigURL, ""))
+ _, decodeErr := sc.Decode(workflowRegistryInstance.RegisterWorkflow(sc.NewTXOpts(), workflowName, [32]byte(common.Hex2Bytes(workflowID)), donID, uint8(0), in.WorkflowConfig.CompiledWorkflowConfig.BinaryURL, in.WorkflowConfig.CompiledWorkflowConfig.ConfigURL, ""))
require.NoError(t, decodeErr, "failed to register workflow")
}
//revive:disable // ignore confusing-results
-func compileWorkflowWithChainlinkCli(t *testing.T, in *WorkflowTestConfig, feedsConsumerAddress common.Address, settingsFile *os.File) (string, string) {
- feedID := "0x018BFE88407000400000000000000000"
-
+func compileWorkflowWithCRECLI(t *testing.T, in *WorkflowTestConfig, feedsConsumerAddress common.Address, feedID string, settingsFile *os.File) (string, string) {
configFile, err := os.CreateTemp("", "config.json")
require.NoError(t, err, "failed to create workflow config file")
+ cleanFeedId := strings.TrimPrefix(feedID, "0x")
+ feedLength := len(cleanFeedId)
+
+ require.GreaterOrEqual(t, feedLength, 32, "feed ID must be at least 32 characters long")
+
+ if feedLength > 32 {
+ cleanFeedId = cleanFeedId[:32]
+ }
+
+ feedIDToUse := "0x" + cleanFeedId
+
workflowConfig := PoRWorkflowConfig{
- FeedID: feedID,
+ FeedID: feedIDToUse,
URL: "https://api.real-time-reserves.verinumus.io/v1/chainlink/proof-of-reserves/TrueUSD",
ConsumerAddress: feedsConsumerAddress.Hex(),
}
@@ -817,18 +751,20 @@ func compileWorkflowWithChainlinkCli(t *testing.T, in *WorkflowTestConfig, feeds
var outputBuffer bytes.Buffer
- compileCmd := exec.Command("chainlink-cli", "workflow", "compile", "-S", settingsFile.Name(), "-c", configFile.Name(), "main.go") // #nosec G204
+ // the CLI expects the workflow code to be located in the same directory as its `go.mod`` file. That's why we assume that the file, which
+ // contains the entrypoint method is always named `main.go`. This is a limitation of the CLI, which we can't change.
+ compileCmd := exec.Command(CRECLICommand, "workflow", "compile", "-S", settingsFile.Name(), "-c", configFile.Name(), "main.go") // #nosec G204
compileCmd.Stdout = &outputBuffer
compileCmd.Stderr = &outputBuffer
- compileCmd.Dir = *in.WorkflowConfig.ChainlinkCLI.FolderLocation
+ compileCmd.Dir = *in.WorkflowConfig.WorkflowFolderLocation
err = compileCmd.Start()
require.NoError(t, err, "failed to start compile command")
err = compileCmd.Wait()
- require.NoError(t, err, "failed to wait for compile command")
-
fmt.Println("Compile output:\n", outputBuffer.String())
+ require.NoError(t, err, "failed to wait for compile command")
+
re := regexp.MustCompile(`Gist URL=([^\s]+)`)
matches := re.FindAllStringSubmatch(outputBuffer.String(), -1)
require.Len(t, matches, 2, "failed to find 2 gist URLs in compile output")
@@ -845,12 +781,12 @@ func compileWorkflowWithChainlinkCli(t *testing.T, in *WorkflowTestConfig, feeds
return workflowGistURL, workflowConfigURL
}
-func preapreChainlinkCliSettingsFile(t *testing.T, sc *seth.Client, capRegAddr, workflowRegistryAddr common.Address, donID uint32, chainSelector uint64, rpcHTTPURL string) *os.File {
- // create chainlink-cli settings file
- settingsFile, err := os.CreateTemp("", ".chainlink-cli-settings.yaml")
- require.NoError(t, err, "failed to create chainlink-cli settings file")
+func preapreCRECLISettingsFile(t *testing.T, sc *seth.Client, capRegAddr, workflowRegistryAddr common.Address, donID uint32, chainSelector uint64, rpcHTTPURL string) *os.File {
+ // create CRE CLI settings file
+ settingsFile, err := os.CreateTemp("", CRECLISettingsFileName)
+ require.NoError(t, err, "failed to create CRE CLI settings file")
- settings := ChainlinkCliSettings{
+ settings := CRECLISettings{
DevPlatform: DevPlatform{
CapabilitiesRegistryAddress: capRegAddr.Hex(),
DonID: donID,
@@ -886,10 +822,10 @@ func preapreChainlinkCliSettingsFile(t *testing.T, sc *seth.Client, capRegAddr,
}
settingsMarshalled, err := yaml.Marshal(settings)
- require.NoError(t, err, "failed to marshal chainlink-cli settings")
+ require.NoError(t, err, "failed to marshal CRE CLI settings")
_, err = settingsFile.Write(settingsMarshalled)
- require.NoError(t, err, "failed to write chainlink-cli settings file")
+ require.NoError(t, err, "failed to write %s settings file", CRECLISettingsFileName)
return settingsFile
}
@@ -897,42 +833,42 @@ func preapreChainlinkCliSettingsFile(t *testing.T, sc *seth.Client, capRegAddr,
func registerWorkflow(t *testing.T, in *WorkflowTestConfig, sc *seth.Client, capRegAddr, workflowRegistryAddr, feedsConsumerAddress common.Address, donID uint32, chainSelector uint64, workflowName, pkey, rpcHTTPURL string) {
// Register workflow directly using the provided binary and config URLs
// This is a legacy solution, probably we can remove it soon
- if in.WorkflowConfig.UseExising && !in.WorkflowConfig.UseChainlinkCLI {
+ if !in.WorkflowConfig.ShouldCompileNewWorkflow && !in.WorkflowConfig.UseCRECLI {
registerWorkflowDirectly(t, in, sc, workflowRegistryAddr, donID, workflowName)
return
}
- // These two env vars are required by the chainlink-cli
+ // These two env vars are required by the CRE CLI
err := os.Setenv("WORKFLOW_OWNER_ADDRESS", sc.MustGetRootKeyAddress().Hex())
require.NoError(t, err, "failed to set WORKFLOW_OWNER_ADDRESS env var")
err = os.Setenv("ETH_PRIVATE_KEY", pkey)
require.NoError(t, err, "failed to set ETH_PRIVATE_KEY env var")
- // create chainlink-cli settings file
- settingsFile := preapreChainlinkCliSettingsFile(t, sc, capRegAddr, workflowRegistryAddr, donID, chainSelector, rpcHTTPURL)
+ // create CRE CLI settings file
+ settingsFile := preapreCRECLISettingsFile(t, sc, capRegAddr, workflowRegistryAddr, donID, chainSelector, rpcHTTPURL)
var workflowGistURL string
var workflowConfigURL string
// compile and upload the workflow, if we are not using an existing one
- if !in.WorkflowConfig.UseExising {
- workflowGistURL, workflowConfigURL = compileWorkflowWithChainlinkCli(t, in, feedsConsumerAddress, settingsFile)
+ if in.WorkflowConfig.ShouldCompileNewWorkflow {
+ workflowGistURL, workflowConfigURL = compileWorkflowWithCRECLI(t, in, feedsConsumerAddress, in.WorkflowConfig.FeedID, settingsFile)
} else {
- workflowGistURL = in.WorkflowConfig.Existing.BinaryURL
- workflowConfigURL = in.WorkflowConfig.Existing.ConfigURL
+ workflowGistURL = in.WorkflowConfig.CompiledWorkflowConfig.BinaryURL
+ workflowConfigURL = in.WorkflowConfig.CompiledWorkflowConfig.ConfigURL
}
// register the workflow
- registerCmd := exec.Command("chainlink-cli", "workflow", "register", workflowName, "-b", workflowGistURL, "-c", workflowConfigURL, "-S", settingsFile.Name(), "-v")
+ registerCmd := exec.Command(CRECLICommand, "workflow", "register", workflowName, "-b", workflowGistURL, "-c", workflowConfigURL, "-S", settingsFile.Name(), "-v")
registerCmd.Stdout = os.Stdout
registerCmd.Stderr = os.Stderr
err = registerCmd.Run()
- require.NoError(t, err, "failed to register workflow using chainlink-cli")
+ require.NoError(t, err, "failed to register workflow using CRE CLI")
}
-func starAndFundNodes(t *testing.T, in *WorkflowTestConfig, bc *blockchain.Output, sc *seth.Client) (*ns.Output, []NodeInfo) {
+func startNodes(t *testing.T, in *WorkflowTestConfig, bc *blockchain.Output) *ns.Output {
// Hack for CI that allows us to dynamically set the chainlink image and version
// CTFv2 currently doesn't support dynamic image and version setting
if os.Getenv("IS_CI") == "true" {
@@ -947,27 +883,25 @@ func starAndFundNodes(t *testing.T, in *WorkflowTestConfig, bc *blockchain.Outpu
nodeset, err := ns.NewSharedDBNodeSet(in.NodeSet, bc)
require.NoError(t, err, "failed to deploy node set")
- nodeClients, err := clclient.New(nodeset.CLNodes)
- require.NoError(t, err, "failed to create chainlink clients")
-
- nodesInfo := getNodesInfo(t, nodeClients)
+ return nodeset
+}
- // Fund all nodes
- for _, nodeInfo := range nodesInfo {
+func fundNodes(t *testing.T, don *devenv.DON, sc *seth.Client) {
+ for _, node := range don.Nodes {
_, err := actions.SendFunds(zerolog.Logger{}, sc, actions.FundsToSendPayload{
- ToAddress: common.HexToAddress(nodeInfo.TransmitterAddress),
+ ToAddress: common.HexToAddress(node.AccountAddr[sc.Cfg.Network.ChainID]),
Amount: big.NewInt(5000000000000000000),
PrivateKey: sc.MustGetRootPrivateKey(),
})
require.NoError(t, err)
}
-
- return nodeset, nodesInfo
}
-func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig, bc *blockchain.Output, capRegAddr common.Address, workflowRegistryAddr common.Address, forwarderAddress common.Address) (*ns.Output, []*clclient.ChainlinkClient) {
- bootstrapNodeInfo := nodesInfo[0]
- workflowNodesetInfo := nodesInfo[1:]
+func configureNodes(t *testing.T, don *devenv.DON, in *WorkflowTestConfig, bc *blockchain.Output, capRegAddr, workflowRegistryAddr, forwarderAddress common.Address) (*ns.Output, []*clclient.ChainlinkClient) {
+ workflowNodeSet := don.Nodes[1:]
+
+ bootstrapNodePeerId, err := nodeToP2PID(don.Nodes[0], keyExtractingTransformFn)
+ require.NoError(t, err, "failed to get bootstrap node peer ID")
// configure the bootstrap node
in.NodeSet.NodeSpecs[0].Node.TestConfigOverrides = fmt.Sprintf(`
@@ -977,6 +911,7 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
[OCR2]
Enabled = true
DatabaseTimeout = '1s'
+ ContractPollInterval = '1s'
[P2P.V2]
Enabled = true
@@ -997,16 +932,20 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
WSURL = '%s'
HTTPURL = '%s'
`,
- bootstrapNodeInfo.PeerID,
- bootstrapNodeInfo.PeerID,
+ bootstrapNodePeerId,
+ bootstrapNodePeerId,
bc.ChainID,
bc.Nodes[0].DockerInternalWSUrl,
bc.Nodes[0].DockerInternalHTTPUrl,
)
+ chainIDInt, err := strconv.Atoi(bc.ChainID)
+ require.NoError(t, err, "failed to convert chain ID to int")
+ chainIDUint64 := mustSafeUint64(int64(chainIDInt))
+
// configure worker nodes with p2p, peering capabilitity (for DON-2-DON communication),
// capability (external) registry, workflow registry and gateway connector (required for reading from workflow registry and for external communication)
- for i := range workflowNodesetInfo {
+ for i := range workflowNodeSet {
in.NodeSet.NodeSpecs[i+1].Node.TestConfigOverrides = fmt.Sprintf(`
[Feature]
LogPoller = true
@@ -1014,6 +953,7 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
[OCR2]
Enabled = true
DatabaseTimeout = '1s'
+ ContractPollInterval = '1s'
[P2P.V2]
Enabled = true
@@ -1052,7 +992,7 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
ChainID = "%s"
[Capabilities.GatewayConnector]
- DonID = "1"
+ DonID = "%s"
ChainIDForNodeKey = "%s"
NodeAddress = '%s'
@@ -1060,19 +1000,20 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
Id = "por_gateway"
URL = "%s"
`,
- bootstrapNodeInfo.PeerID,
- bootstrapNodeInfo.PeerID,
+ bootstrapNodePeerId,
+ bootstrapNodePeerId,
bc.ChainID,
bc.Nodes[0].DockerInternalWSUrl,
bc.Nodes[0].DockerInternalHTTPUrl,
- workflowNodesetInfo[i].TransmitterAddress,
+ workflowNodeSet[i].AccountAddr[chainIDUint64],
forwarderAddress.Hex(),
capRegAddr,
bc.ChainID,
workflowRegistryAddr.Hex(),
bc.ChainID,
+ strconv.FormatUint(uint64(in.WorkflowConfig.DonID), 10),
bc.ChainID,
- workflowNodesetInfo[i].TransmitterAddress,
+ workflowNodeSet[i].AccountAddr[chainIDUint64],
"ws://node0:5003/node", // bootstrap node exposes gateway port on 5003
)
}
@@ -1088,12 +1029,49 @@ func configureNodes(t *testing.T, nodesInfo []NodeInfo, in *WorkflowTestConfig,
return nodeset, nodeClients
}
-func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodesInfo []NodeInfo, bc *blockchain.Output, ocr3CapabilityAddress common.Address) {
- bootstrapNodeInfo := nodesInfo[0]
- workflowNodesetInfo := nodesInfo[1:]
+func reinitialiseJDClient(t *testing.T, ctfEnv *deployment.Environment, jdOutput *jd.Output, nodeOutput *ns.Output) deployment.Environment {
+ nodeInfo, err := getNodeInfo(nodeOutput, 1)
+ require.NoError(t, err, "failed to get node info")
+
+ jdConfig := devenv.JDConfig{
+ GRPC: jdOutput.HostGRPCUrl,
+ WSRPC: jdOutput.DockerWSRPCUrl,
+ Creds: insecure.NewCredentials(),
+ NodeInfo: nodeInfo,
+ }
+
+ offChain, err := devenv.NewJDClient(context.Background(), jdConfig)
+ require.NoError(t, err, "failed to create JD client")
+
+ ctfEnv.Offchain = offChain
+
+ return *ctfEnv
+}
+
+func mustSafeUint64(input int64) uint64 {
+ if input < 0 {
+ panic(fmt.Errorf("int64 %d is below uint64 min value", input))
+ }
+ return uint64(input)
+}
+
+func createNodeJobsWithJd(t *testing.T, ctfEnv *deployment.Environment, don *devenv.DON, bc *blockchain.Output, keystoneContractSet keystone_changeset.ContractSet) {
+ // if there's only one OCR3 contract in the set, we can use `nil` as the address to get its instance
+ ocr3Contract, err := keystoneContractSet.GetOCR3Contract(nil)
+ require.NoError(t, err, "failed to get OCR3 contract address")
+
+ ocr3CapabilityAddress := ocr3Contract.Address().Hex()
+
+ chainIDInt, err := strconv.Atoi(bc.ChainID)
+ require.NoError(t, err, "failed to convert chain ID to int")
+ chainIDUint64 := mustSafeUint64(int64(chainIDInt))
+
+ bootstrapNodePeerId, err := nodeToP2PID(don.Nodes[0], keyExtractingTransformFn)
+ require.NoError(t, err, "failed to get bootstrap node peer ID")
+
+ jobCount := 2 + (len(don.Nodes)-1)*3
+ errCh := make(chan error, jobCount)
- // Create gateway and bootstrap (ocr3) jobs for the bootstrap node
- bootstrapNode := nodeClients[0]
var wg sync.WaitGroup
wg.Add(1)
go func() {
@@ -1102,45 +1080,52 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
bootstrapJobSpec := fmt.Sprintf(`
type = "bootstrap"
schemaVersion = 1
+ externalJobID = "%s"
name = "Botostrap"
contractID = "%s"
contractConfigTrackerPollInterval = "1s"
contractConfigConfirmations = 1
relay = "evm"
-
[relayConfig]
chainID = %s
providerType = "ocr3-capability"
- `, ocr3CapabilityAddress, bc.ChainID)
- r, _, bootErr := bootstrapNode.CreateJobRaw(bootstrapJobSpec)
- assert.NoError(t, bootErr, "failed to create bootstrap job for the bootstrap node")
- assert.Empty(t, r.Errors, "failed to create bootstrap job for the bootstrap node")
+ `, uuid.NewString(),
+ ocr3CapabilityAddress,
+ bc.ChainID)
+
+ bootstrapJobRequest := &jobv1.ProposeJobRequest{
+ NodeId: don.Nodes[0].NodeID,
+ Spec: bootstrapJobSpec,
+ }
+
+ _, bootErr := ctfEnv.Offchain.ProposeJob(context.Background(), bootstrapJobRequest)
+ if bootErr != nil {
+ errCh <- errors.Wrapf(bootErr, "failed to propose bootstrap job")
+ return
+ }
gatewayJobSpec := fmt.Sprintf(`
type = "gateway"
schemaVersion = 1
- name = "PoR Gateway"
+ externalJobID = "%s"
+ name = "Gateway"
forwardingAllowed = false
-
[gatewayConfig.ConnectionManagerConfig]
AuthChallengeLen = 10
AuthGatewayId = "por_gateway"
AuthTimestampToleranceSec = 5
HeartbeatIntervalSec = 20
-
[[gatewayConfig.Dons]]
DonId = "1"
F = 1
HandlerName = "web-api-capabilities"
[gatewayConfig.Dons.HandlerConfig]
MaxAllowedMessageAgeSec = 1_000
-
[gatewayConfig.Dons.HandlerConfig.NodeRateLimiter]
GlobalBurst = 10
GlobalRPS = 50
PerSenderBurst = 10
PerSenderRPS = 10
-
[[gatewayConfig.Dons.Members]]
Address = "%s"
Name = "Workflow Node 1"
@@ -1153,7 +1138,6 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
[[gatewayConfig.Dons.Members]]
Address = "%s"
Name = "Workflow Node 4"
-
[gatewayConfig.NodeServerConfig]
HandshakeTimeoutMillis = 1_000
MaxRequestBytes = 100_000
@@ -1162,7 +1146,6 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
ReadTimeoutMillis = 1_000
RequestTimeoutMillis = 10_000
WriteTimeoutMillis = 1_000
-
[gatewayConfig.UserServerConfig]
ContentTypeHeader = "application/jsonrpc"
MaxRequestBytes = 100_000
@@ -1171,24 +1154,30 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
ReadTimeoutMillis = 1_000
RequestTimeoutMillis = 10_000
WriteTimeoutMillis = 1_000
-
[gatewayConfig.HTTPClientConfig]
MaxResponseBytes = 100_000_000
`,
+ uuid.NewString(),
// ETH keys of the workflow nodes
- workflowNodesetInfo[0].TransmitterAddress,
- workflowNodesetInfo[1].TransmitterAddress,
- workflowNodesetInfo[2].TransmitterAddress,
- workflowNodesetInfo[3].TransmitterAddress,
+ don.Nodes[1].AccountAddr[chainIDUint64],
+ don.Nodes[2].AccountAddr[chainIDUint64],
+ don.Nodes[3].AccountAddr[chainIDUint64],
+ don.Nodes[4].AccountAddr[chainIDUint64],
)
- r, _, gatewayErr := bootstrapNode.CreateJobRaw(gatewayJobSpec)
- assert.NoError(t, gatewayErr, "failed to create gateway job for the bootstrap node")
- assert.Empty(t, r.Errors, "failed to create gateway job for the bootstrap node")
+ gatewayJobRequest := &jobv1.ProposeJobRequest{
+ NodeId: don.Nodes[0].NodeID,
+ Spec: gatewayJobSpec,
+ }
+
+ _, gateErr := ctfEnv.Offchain.ProposeJob(context.Background(), gatewayJobRequest)
+ if gateErr != nil {
+ errCh <- errors.Wrapf(gateErr, "failed to propose gateway job for the bootstrap node")
+ }
}()
// for each capability that's required by the workflow, create a job for workflow each node
- for i, nodeClient := range nodeClients {
+ for i, node := range don.Nodes {
// First node is a bootstrap node, so we skip it
if i == 0 {
continue
@@ -1199,22 +1188,35 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
defer wg.Done()
// since we are using a capability that is not bundled-in, we need to copy it to the Docker container
// and point the job to the copied binary
+
+ // failed to propose job. err: rpc error: code = Internal desc = failed to propose job to node: failed to generate a job based on spec: unknown job type: standardcapabilities
cronJobSpec := fmt.Sprintf(`
type = "standardcapabilities"
schemaVersion = 1
+ externalJobID = "%s"
name = "cron-capabilities"
forwardingAllowed = false
command = "/home/capabilities/%s"
config = ""
- `, cronCapabilityAssetFile)
+ `,
+ uuid.NewString(),
+ cronCapabilityAssetFile)
- response, _, errCron := nodeClient.CreateJobRaw(cronJobSpec)
- assert.NoError(t, errCron, "failed to create cron job")
- assert.Empty(t, response.Errors, "failed to create cron job")
+ cronJobRequest := &jobv1.ProposeJobRequest{
+ NodeId: node.NodeID,
+ Spec: cronJobSpec,
+ }
- computeJobSpec := `
+ _, cronErr := ctfEnv.Offchain.ProposeJob(context.Background(), cronJobRequest)
+ if cronErr != nil {
+ errCh <- errors.Wrapf(cronErr, "failed to propose cron job for node %s", node.NodeID)
+ return
+ }
+
+ computeJobSpec := fmt.Sprintf(`
type = "standardcapabilities"
schemaVersion = 1
+ externalJobID = "%s"
name = "compute-capabilities"
forwardingAllowed = false
command = "__builtin_custom-compute-action"
@@ -1226,15 +1228,24 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
perSenderRPS = 1.0
perSenderBurst = 5
"""
- `
+ `,
+ uuid.NewString())
- response, _, errCompute := nodeClient.CreateJobRaw(computeJobSpec)
- assert.NoError(t, errCompute, "failed to create compute job")
- assert.Empty(t, response.Errors, "failed to create compute job")
+ computeJobRequest := &jobv1.ProposeJobRequest{
+ NodeId: node.NodeID,
+ Spec: computeJobSpec,
+ }
+
+ _, compErr := ctfEnv.Offchain.ProposeJob(context.Background(), computeJobRequest)
+ if compErr != nil {
+ errCh <- errors.Wrapf(compErr, "failed to propose compute job for node %s", node.NodeID)
+ return
+ }
consensusJobSpec := fmt.Sprintf(`
type = "offchainreporting2"
schemaVersion = 1
+ externalJobID = "%s"
name = "Keystone OCR3 Consensus Capability"
contractID = "%s"
ocrKeyBundleID = "%s"
@@ -1244,106 +1255,441 @@ func createNodeJobs(t *testing.T, nodeClients []*clclient.ChainlinkClient, nodes
relay = "evm"
pluginType = "plugin"
transmitterID = "%s"
-
[relayConfig]
chainID = "%s"
-
[pluginConfig]
command = "/usr/local/bin/chainlink-ocr3-capability"
ocrVersion = 3
pluginName = "ocr-capability"
providerType = "ocr3-capability"
telemetryType = "plugin"
-
[onchainSigningStrategy]
strategyName = 'multi-chain'
[onchainSigningStrategy.config]
evm = "%s"
`,
+ uuid.NewString(),
ocr3CapabilityAddress,
- nodesInfo[i].OcrKeyBundleID,
- bootstrapNodeInfo.PeerID,
+ node.Ocr2KeyBundleID,
+ bootstrapNodePeerId,
"node0:5001",
- nodesInfo[i].TransmitterAddress,
+ node.AccountAddr[chainIDUint64],
bc.ChainID,
- nodesInfo[i].OcrKeyBundleID,
+ node.Ocr2KeyBundleID,
)
- fmt.Println("consensusJobSpec", consensusJobSpec)
- response, _, errCons := nodeClient.CreateJobRaw(consensusJobSpec)
- assert.NoError(t, errCons, "failed to create consensus job")
- assert.Empty(t, response.Errors, "failed to create consensus job")
+
+ consensusJobRequest := &jobv1.ProposeJobRequest{
+ NodeId: node.NodeID,
+ Spec: consensusJobSpec,
+ }
+
+ _, consErr := ctfEnv.Offchain.ProposeJob(context.Background(), consensusJobRequest)
+ if consErr != nil {
+ errCh <- errors.Wrapf(consErr, "failed to propose consensus job for node %s ", node.NodeID)
+ }
}()
}
wg.Wait()
+
+ close(errCh)
+
+ errFound := false
+ for err := range errCh {
+ errFound = true
+ //nolint:testifylint // we want to assert here to catch all errors
+ assert.NoError(t, err, "job creation/acception failed")
+ }
+
+ require.False(t, errFound, "failed to create at least one job")
+}
+
+func noOpTransformFn(value string) string {
+ return value
+}
+
+func keyExtractingTransformFn(value string) string {
+ parts := strings.Split(value, "_")
+ if len(parts) > 1 {
+ return parts[len(parts)-1]
+ }
+ return value
}
-func registerDONAndCapabilities(t *testing.T, capRegAddr common.Address, hashedCapabilities [][32]byte, nodesInfo []NodeInfo, sc *seth.Client) {
- // Register node operators, nodes and DON in the Capabilities registry
- nopsToAdd := make([]cr_wrapper.CapabilitiesRegistryNodeOperator, len(nodesInfo)-1)
- nodesToAdd := make([]cr_wrapper.CapabilitiesRegistryNodeParams, len(nodesInfo)-1)
- donNodes := make([][32]byte, len(nodesInfo)-1)
+func nodeToP2PID(node devenv.Node, transformFn func(string) string) (string, error) {
+ for _, label := range node.Labels() {
+ if label.Key == devenv.NodeLabelP2PIDType {
+ if label.Value == nil {
+ return "", fmt.Errorf("p2p label value is nil for node %s", node.Name)
+ }
+ return transformFn(*label.Value), nil
+ }
+ }
+
+ return "", fmt.Errorf("p2p label not found for node %s", node.Name)
+}
+
+func configureWorkflowDON(t *testing.T, ctfEnv *deployment.Environment, don *devenv.DON, chainSelector uint64) {
+ kcrAllCaps := []keystone_changeset.DONCapabilityWithConfig{
+ {
+ Capability: kcr.CapabilitiesRegistryCapability{
+ LabelledName: "offchain_reporting",
+ Version: "1.0.0",
+ CapabilityType: 2, // CONSENSUS
+ ResponseType: 0, // REPORT
+ },
+ Config: &capabilitiespb.CapabilityConfig{},
+ },
+ {
+ Capability: kcr.CapabilitiesRegistryCapability{
+ LabelledName: "write_geth-testnet",
+ Version: "1.0.0",
+ CapabilityType: 3, // TARGET
+ ResponseType: 1, // OBSERVATION_IDENTICAL
+ },
+ Config: &capabilitiespb.CapabilityConfig{},
+ },
+ {
+ Capability: kcr.CapabilitiesRegistryCapability{
+ LabelledName: "cron-trigger",
+ Version: "1.0.0",
+ CapabilityType: uint8(0), // trigger
+ },
+ Config: &capabilitiespb.CapabilityConfig{},
+ },
+ {
+ Capability: kcr.CapabilitiesRegistryCapability{
+ LabelledName: "custom-compute",
+ Version: "1.0.0",
+ CapabilityType: uint8(1), // action
+ },
+ Config: &capabilitiespb.CapabilityConfig{},
+ },
+ }
- for i, node := range nodesInfo {
- // skip the first node, as it's the bootstrap node
- // it doesn't have any capabilities that are required by the workflow
+ peerIds := make([]string, len(don.Nodes)-1)
+ for i, node := range don.Nodes {
if i == 0 {
continue
}
- nopsToAdd[i-1] = cr_wrapper.CapabilitiesRegistryNodeOperator{
- Admin: common.HexToAddress(node.TransmitterAddress),
- Name: fmt.Sprintf("NOP %d", i),
+
+ p2pId, err := nodeToP2PID(node, noOpTransformFn)
+ require.NoError(t, err, "failed to get p2p id for node %s", node.Name)
+
+ peerIds[i-1] = p2pId
+ }
+
+ nop := keystone_changeset.NOP{
+ Name: "NOP 1",
+ Nodes: peerIds,
+ }
+
+ donName := "keystone-don"
+ donCap := keystone_changeset.DonCapabilities{
+ Name: donName,
+ F: 1,
+ Nops: []keystone_changeset.NOP{nop},
+ Capabilities: kcrAllCaps,
+ }
+
+ transmissionSchedule := make([]int, len(don.Nodes)-1)
+ for i := range transmissionSchedule {
+ transmissionSchedule[i] = i + 1
+ }
+
+ // values supplied by Alexandr Yepishev as the expected values for OCR3 config
+ oracleConfig := keystone_changeset.OracleConfig{
+ DeltaProgressMillis: 5000,
+ DeltaResendMillis: 5000,
+ DeltaInitialMillis: 5000,
+ DeltaRoundMillis: 2000,
+ DeltaGraceMillis: 500,
+ DeltaCertifiedCommitRequestMillis: 1000,
+ DeltaStageMillis: 30000,
+ MaxRoundsPerEpoch: 10,
+ TransmissionSchedule: transmissionSchedule,
+ MaxDurationQueryMillis: 1000,
+ MaxDurationObservationMillis: 1000,
+ MaxDurationAcceptMillis: 1000,
+ MaxDurationTransmitMillis: 1000,
+ MaxFaultyOracles: 1,
+ MaxQueryLengthBytes: 1000000,
+ MaxObservationLengthBytes: 1000000,
+ MaxReportLengthBytes: 1000000,
+ MaxRequestBatchSize: 1000,
+ UniqueReports: true,
+ }
+
+ cfg := keystone_changeset.InitialContractsCfg{
+ RegistryChainSel: chainSelector,
+ Dons: []keystone_changeset.DonCapabilities{donCap},
+ OCR3Config: &oracleConfig,
+ }
+
+ _, err := keystone_changeset.ConfigureInitialContractsChangeset(*ctfEnv, cfg)
+ require.NoError(t, err, "failed to configure initial contracts")
+}
+
+func startJobDistributor(t *testing.T, in *WorkflowTestConfig) *jd.Output {
+ if os.Getenv("IS_CI") == "true" {
+ jdImage := ctfconfig.MustReadEnvVar_String(e2eJobDistributorImageEnvVarName)
+ jdVersion := os.Getenv(e2eJobDistributorVersionEnvVarName)
+ in.JD.Image = fmt.Sprintf("%s:%s", jdImage, jdVersion)
+ }
+ jdOutput, err := jd.NewJD(in.JD)
+ require.NoError(t, err, "failed to create new job distributor")
+
+ return jdOutput
+}
+
+func getLogFileHandles(t *testing.T, l zerolog.Logger, ns *ns.Output) ([]*os.File, error) {
+ var logFiles []*os.File
+
+ var belongsToCurrentEnv = func(filePath string) bool {
+ for i, clNode := range ns.CLNodes {
+ if clNode == nil {
+ continue
+ }
+
+ // skip the first node, as it's the bootstrap node
+ if i == 0 {
+ continue
+ }
+
+ if strings.EqualFold(filePath, clNode.Node.ContainerName+".log") {
+ return true
+ }
}
+ return false
+ }
- var peerID ragetypes.PeerID
- err := peerID.UnmarshalText([]byte(node.PeerID))
- require.NoError(t, err, "failed to unmarshal peer ID")
+ logsDir := "logs/docker-" + t.Name()
- nodesToAdd[i-1] = cr_wrapper.CapabilitiesRegistryNodeParams{
- NodeOperatorId: uint32(i), //nolint:gosec // disable G115
- Signer: common.BytesToHash(node.Signer.Bytes()),
- P2pId: peerID,
- EncryptionPublicKey: [32]byte{1, 2, 3, 4, 5},
- HashedCapabilityIds: hashedCapabilities,
+ fileWalkErr := filepath.Walk(logsDir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() && belongsToCurrentEnv(info.Name()) {
+ file, fileErr := os.Open(path)
+ if fileErr != nil {
+ return fmt.Errorf("failed to open file %s: %w", path, fileErr)
+ }
+ logFiles = append(logFiles, file)
}
+ return nil
+ })
- donNodes[i-1] = peerID
+ expectedLogCount := len(ns.CLNodes) - 1
+ if len(logFiles) != expectedLogCount {
+ l.Warn().Int("Expected", expectedLogCount).Int("Got", len(logFiles)).Msg("Number of log files does not match number of worker nodes. Some logs might be missing.")
}
- capabilitiesRegistryInstance, err := cr_wrapper.NewCapabilitiesRegistry(capRegAddr, sc.Client)
- require.NoError(t, err, "failed to create capabilities registry instance")
+ if fileWalkErr != nil {
+ l.Error().Err(fileWalkErr).Msg("Error walking through log files. Will not look for report transmission transaction hashes")
+ return nil, fileWalkErr
+ }
- // Add NOPs to capabilities registry
- _, decodeErr := sc.Decode(capabilitiesRegistryInstance.AddNodeOperators(
- sc.NewTXOpts(),
- nopsToAdd,
- ))
- require.NoError(t, decodeErr, "failed to add NOPs to capabilities registry")
+ return logFiles, nil
+}
- // Add nodes to capabilities registry
- _, decodeErr = sc.Decode(capabilitiesRegistryInstance.AddNodes(
- sc.NewTXOpts(),
- nodesToAdd,
- ))
- require.NoError(t, decodeErr, "failed to add nodes to capabilities registry")
+// This function is used to go through Chainlink Node logs and look for entries related to report transmissions.
+// Once such a log entry is found, it looks for transaction hash and then it tries to decode the transaction and print the result.
+func debugReportTransmissions(logFiles []*os.File, l zerolog.Logger, wsRPCURL string) {
+ /*
+ Example log entry:
+ 2025-01-28T14:44:48.080Z [DEBUG] Node sent transaction multinode@v0.0.0-20250121205514-f73e2f86c23b/transaction_sender.go:180 chainID=1337 logger=EVM.1337.TransactionSender tx={"type":"0x0","chainId":"0x539","nonce":"0x0","to":"0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9","gas":"0x61a80","gasPrice":"0x3b9aca00","maxPriorityFeePerGas":null,"maxFeePerGas":null,"value":"0x0","input":"0x11289565000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c853000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000010d010f715db03509d388f706e16137722000e26aa650a64ac826ae8e5679cdf57fd96798ed50000000010000000100000a9c593aaed2f5371a5bc0779d1b8ea6f9c7d37bfcbb876a0a9444dbd36f64306466323239353031f39fd6e51aad88f6f4ce6ab8827279cfffb92266000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001018bfe88407000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb5c162c8000000000000000000000000000000000000000000000000000000006798ed37000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000e700d4c57250eac9dc925c951154c90c1b6017944322fb2075055d8bdbe19000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041561c171b7465e8efef35572ef82adedb49ea71b8344a34a54ce5e853f80ca1ad7d644ebe710728f21ebfc3e2407bd90173244f744faa011c3a57213c8c585de90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004165e6f3623acc43f163a58761655841bfebf3f6b4ea5f8d34c64188036b0ac23037ebbd3854b204ca26d828675395c4b9079ca068d9798326eb8c93f26570a1080100000000000000000000000000000000000000000000000000000000000000","v":"0xa96","r":"0x168547e96e7088c212f85a4e8dddce044bbb2abfd5ccc8a5451fdfcb812c94e5","s":"0x2a735a3df046632c2aaa7e583fe161113f3345002e6c9137bbfa6800a63f28a4","hash":"0x3fc5508310f8deef09a46ad594dcc5dc9ba415319ef1dfa3136335eb9e87ff4d"} version=2.19.0@05c05a9
+
+ What we are looking for:
+ "hash":"0x3fc5508310f8deef09a46ad594dcc5dc9ba415319ef1dfa3136335eb9e87ff4d"
+ */
+ reportTransmissionTxHashPattern := regexp.MustCompile(`"hash":"(0x[0-9a-fA-F]+)"`)
+
+ // let's be prudent and assume that in extreme scenario when feed price isn't updated, but
+ // transmission is still sent, we might have multiple transmissions per node, and if we want
+ // to avoid blocking on the channel, we need to have a higher buffer
+ resultsCh := make(chan string, len(logFiles)*4)
+
+ wg := &sync.WaitGroup{}
+ for _, f := range logFiles {
+ wg.Add(1)
+ file := f
- capRegConfig := make([]cr_wrapper.CapabilitiesRegistryCapabilityConfiguration, len(hashedCapabilities))
- for i, hashed := range hashedCapabilities {
- capRegConfig[i] = cr_wrapper.CapabilitiesRegistryCapabilityConfiguration{
- CapabilityId: hashed,
- Config: []byte(""),
+ go func() {
+ defer wg.Done()
+
+ scanner := bufio.NewScanner(file)
+ scanner.Split(bufio.ScanLines)
+
+ for scanner.Scan() {
+ jsonLogLine := scanner.Text()
+
+ if !strings.Contains(jsonLogLine, "Node sent transaction") {
+ continue
+ }
+
+ match := reportTransmissionTxHashPattern.MatchString(jsonLogLine)
+ if match {
+ resultsCh <- reportTransmissionTxHashPattern.FindStringSubmatch(jsonLogLine)[1]
+ }
+ }
+ }()
+ }
+
+ wg.Wait()
+ close(resultsCh)
+
+ if len(resultsCh) == 0 {
+ l.Error().Msg("❌ No report transmissions found in Chainlink Node logs.")
+ return
+ }
+
+ // required as Seth prints transaction traces to stdout with debug level
+ _ = os.Setenv(seth.LogLevelEnvVar, "debug")
+
+ sc, err := seth.NewClientBuilder().
+ WithRpcUrl(wsRPCURL).
+ WithReadOnlyMode().
+ WithGethWrappersFolders([]string{"../../../core/gethwrappers/keystone/generated"}). // point Seth to the folder with keystone geth wrappers, so that it can load contract ABIs
+ Build()
+
+ if err != nil {
+ l.Error().Err(err).Msg("Failed to create seth client")
+ return
+ }
+
+ for txHash := range resultsCh {
+ l.Info().Msgf("🔍 Tracing report transmission transaction %s", txHash)
+ // set tracing level to all to trace also successful transactions
+ sc.Cfg.TracingLevel = seth.TracingLevel_All
+ tx, _, err := sc.Client.TransactionByHash(context.Background(), common.HexToHash(txHash))
+ if err != nil {
+ l.Warn().Err(err).Msgf("Failed to get transaction by hash %s", txHash)
+ continue
+ }
+ _, decodedErr := sc.DecodeTx(tx)
+
+ if decodedErr != nil {
+ l.Error().Err(decodedErr).Msgf("Transmission transaction %s failed due to %s", txHash, decodedErr.Error())
+ continue
}
}
+}
- // Add nodeset to capabilities registry
- _, decodeErr = sc.Decode(capabilitiesRegistryInstance.AddDON(
- sc.NewTXOpts(),
- donNodes,
- capRegConfig,
- true, // is public
- true, // accepts workflows
- uint8(1), // max number of malicious nodes
- ))
- require.NoError(t, decodeErr, "failed to add DON to capabilities registry")
+// this function is used to print debug information from Chainlink Node logs
+// it checks whether workflow was executing, OCR was executing and whether reports were sent
+// and if they were, it traces each report transmission transaction
+func printTestDebug(t *testing.T, l zerolog.Logger, ns *ns.Output, wsRPCURL string) {
+ logFiles, err := getLogFileHandles(t, l, ns)
+ if err != nil {
+ l.Error().Err(err).Msg("Failed to get log file handles. No debug information will be printed")
+ return
+ }
+
+ defer func() {
+ for _, f := range logFiles {
+ _ = f.Close()
+ }
+ }()
+
+ l.Info().Msg("🔍 Debug information from Chainlink Node logs:")
+
+ // assuming one bootstrap node
+ workflowNodeCount := len(ns.CLNodes) - 1
+ if !checkIfWorkflowWasExecuting(logFiles, workflowNodeCount) {
+ l.Error().Msg("❌ Workflow was not executing")
+ return
+ } else {
+ l.Info().Msg("✅ Workflow was executing")
+ }
+
+ if !checkIfOCRWasExecuting(logFiles, workflowNodeCount) {
+ l.Error().Msg("❌ OCR was not executing")
+ return
+ } else {
+ l.Info().Msg("✅ OCR was executing")
+ }
+
+ if !checkIfAtLeastOneReportWasSent(logFiles, workflowNodeCount) {
+ l.Error().Msg("❌ Reports were not sent")
+ return
+ } else {
+ l.Info().Msg("✅ Reports were sent")
+
+ // debug report transmissions
+ debugReportTransmissions(logFiles, l, wsRPCURL)
+ }
+}
+
+func checkIfLogsHaveText(logFiles []*os.File, bufferSize int, expectedText string, validationFn func(int) bool) bool {
+ wg := &sync.WaitGroup{}
+
+ resultsCh := make(chan struct{}, bufferSize)
+
+ for _, f := range logFiles {
+ wg.Add(1)
+ file := f
+
+ go func() {
+ defer func() {
+ wg.Done()
+ // reset file pointer to the beginning of the file
+ // so that subsequent reads start from the beginning
+ _, _ = file.Seek(0, io.SeekStart)
+ }()
+
+ scanner := bufio.NewScanner(file)
+ scanner.Split(bufio.ScanLines)
+
+ for scanner.Scan() {
+ jsonLogLine := scanner.Text()
+
+ if strings.Contains(jsonLogLine, expectedText) {
+ resultsCh <- struct{}{}
+ return
+ }
+ }
+ }()
+ }
+
+ wg.Wait()
+ close(resultsCh)
+
+ var found int
+ for range resultsCh {
+ found++
+ }
+
+ return validationFn(found)
+}
+
+func exactCountValidationFn(expected int) func(int) bool {
+ return func(found int) bool {
+ return found == expected
+ }
+}
+
+func checkIfWorkflowWasExecuting(logFiles []*os.File, workflowNodeCount int) bool {
+ return checkIfLogsHaveText(logFiles, workflowNodeCount, "step request enqueued", exactCountValidationFn(workflowNodeCount))
+}
+
+func checkIfOCRWasExecuting(logFiles []*os.File, workflowNodeCount int) bool {
+ return checkIfLogsHaveText(logFiles, workflowNodeCount, "✅ committed outcome", exactCountValidationFn(workflowNodeCount))
+}
+
+func checkIfAtLeastOneReportWasSent(logFiles []*os.File, workflowNodeCount int) bool {
+ // we are looking for "Node sent transaction" log entry, which might appear various times in the logs
+ // but most probably not in the logs of all nodes, since they take turns in sending reports
+ // our buffer must be large enough to capture all the possible log entries in order to avoid channel blocking
+ bufferSize := workflowNodeCount * 4
+
+ return checkIfLogsHaveText(logFiles, bufferSize, "Node sent transaction", func(found int) bool { return found > 0 })
+}
+
+func logTestInfo(l zerolog.Logger, feedId, workflowName, feedConsumerAddr, forwarderAddr string) {
+ l.Info().Msg("------ Test configuration:")
+ l.Info().Msgf("Feed ID: %s", feedId)
+ l.Info().Msgf("Workflow name: %s", workflowName)
+ l.Info().Msgf("FeedConsumer address: %s", feedConsumerAddr)
+ l.Info().Msgf("KeystoneForwarder address: %s", forwarderAddr)
}
/*
@@ -1351,27 +1697,37 @@ func registerDONAndCapabilities(t *testing.T, capRegAddr common.Address, hashedC
Do not use this test as a template for your tests. It's hacky, since we were working under time pressure. We will soon refactor it follow best practices
and a golden example. Apart from its structure what is currently missing is:
-- using `chainlink/deployment` to deploy and configure all the contracts
- using Job Distribution to create jobs for the nodes
-- using only `chainlink-cli` to register the workflow
- using a mock service to provide the feed data
*/
func TestKeystoneWithOCR3Workflow(t *testing.T) {
- testLogger := logging.GetTestLogger(t)
-
- // Define and load the test configuration
- donID := uint32(1)
- workflowName := "abcdefgasd"
- feedID := "018bfe8840700040000000000000000000000000000000000000000000000000" // without 0x prefix!
- feedBytes := common.HexToHash(feedID)
+ testLogger := framework.L
+
+ // we need to use double-pointers, so that what's captured in the cleanup function is a pointer, not the actual object,
+ // which is only set later in the test, after the cleanup function is defined
+ var nodes **ns.Output
+ var wsRPCURL *string
+
+ // clean up is LIFO, so we need to make sure we execute the debug report transmission after logs are written down
+ // by function added to clean up by framework.Load() method
+ t.Cleanup(func() {
+ if t.Failed() {
+ if nodes == nil {
+ testLogger.Warn().Msg("nodeset output is nil, skipping debug report transmission")
+ return
+ }
+ printTestDebug(t, testLogger, *nodes, *wsRPCURL)
+ }
+ })
+ // Load test configuration
in, err := framework.Load[WorkflowTestConfig](t)
require.NoError(t, err, "couldn't load test config")
validateInputsAndEnvVars(t, in)
pkey := os.Getenv("PRIVATE_KEY")
- // Create a new blockchain network
+ // Create a new blockchain network and Seth client to interact with it
bc, err := blockchain.NewBlockchainNetwork(in.BlockchainA)
require.NoError(t, err)
@@ -1381,66 +1737,48 @@ func TestKeystoneWithOCR3Workflow(t *testing.T) {
Build()
require.NoError(t, err, "failed to create seth client")
+ // Start job distributor
+ jdOutput := startJobDistributor(t, in)
+
+ // Deploy the DON
+ nodeOutput := startNodes(t, in, bc)
+
// Prepare the chainlink/deployment environment
- ctfEnv, chainSelector := buildChainlinkDeploymentEnv(t, sc)
+ ctfEnv, don, chainSelector := buildChainlinkDeploymentEnv(t, jdOutput, nodeOutput, bc, sc)
- // Define required capabilities
- // These need to match the capabilities that are required by the workflow,
- // which in our case is a Proof-of-Reserves workflow
- allCaps := []cr_wrapper.CapabilitiesRegistryCapability{
- {
- LabelledName: "offchain_reporting",
- Version: "1.0.0",
- CapabilityType: 2, // CONSENSUS
- ResponseType: 0, // REPORT
- },
- {
- LabelledName: "write_geth-testnet",
- Version: "1.0.0",
- CapabilityType: 3, // TARGET
- ResponseType: 1, // OBSERVATION_IDENTICAL
- },
- {
- LabelledName: "cron-trigger",
- Version: "1.0.0",
- CapabilityType: uint8(0), // trigger
- },
- {
- LabelledName: "custom-compute",
- Version: "1.0.0",
- CapabilityType: uint8(1), // action
- },
- }
- capRegAddr, hashedCapabilities := prepareCapabilitiesRegistry(t, sc, allCaps)
+ // Fund the nodes
+ fundNodes(t, don, sc)
- // Deploy keystone forwarder contract
- forwarderAddress := deployKeystoneForwarder(t, testLogger, ctfEnv, chainSelector)
+ // Deploy keystone contracts (forwarder, capability registry, ocr3 capability)
+ keystoneContractSet := deployKeystoneContracts(t, testLogger, ctfEnv, chainSelector)
// Deploy and pre-configure workflow registry contract
- workflowRegistryAddr := prepareWorkflowRegistry(t, testLogger, ctfEnv, chainSelector, sc, donID)
+ workflowRegistryAddr := prepareWorkflowRegistry(t, testLogger, ctfEnv, chainSelector, sc, in.WorkflowConfig.DonID)
// Deploy and configure Keystone Feeds Consumer contract
- feedsConsumerAddress := prepareFeedsConsumer(t, testLogger, ctfEnv, chainSelector, sc, forwarderAddress, workflowName)
-
- // Register the workflow (either via chainlink-cli or by calling the workflow registry directly)
- registerWorkflow(t, in, sc, capRegAddr, workflowRegistryAddr, feedsConsumerAddress, donID, chainSelector, workflowName, pkey, bc.Nodes[0].HostHTTPUrl)
-
- // Deploy and fund the DON
- _, nodesInfo := starAndFundNodes(t, in, bc, sc)
- _, nodeClients := configureNodes(t, nodesInfo, in, bc, capRegAddr, workflowRegistryAddr, forwarderAddress)
+ feedsConsumerAddress := prepareFeedsConsumer(t, testLogger, ctfEnv, chainSelector, sc, keystoneContractSet.Forwarder.Address(), in.WorkflowConfig.WorkflowName)
- // Deploy OCR3 Capability contract
- ocr3CapabilityAddress := deployOCR3Capability(t, testLogger, sc)
+ // Register the workflow (either via CRE CLI or by calling the workflow registry directly)
+ registerWorkflow(t, in, sc, keystoneContractSet.CapabilitiesRegistry.Address(), workflowRegistryAddr, feedsConsumerAddress, in.WorkflowConfig.DonID, chainSelector, in.WorkflowConfig.WorkflowName, pkey, bc.Nodes[0].HostHTTPUrl)
- // Create OCR3 and capability jobs for each node
- createNodeJobs(t, nodeClients, nodesInfo, bc, ocr3CapabilityAddress)
+ // Create OCR3 and capability jobs for each node JD
+ ns, _ := configureNodes(t, don, in, bc, keystoneContractSet.CapabilitiesRegistry.Address(), workflowRegistryAddr, keystoneContractSet.Forwarder.Address())
+ // JD client needs to be reinitialised after restarting nodes
+ ctfEnv = ptr.Ptr(reinitialiseJDClient(t, ctfEnv, jdOutput, nodeOutput))
+ createNodeJobsWithJd(t, ctfEnv, don, bc, keystoneContractSet)
- // Register DON and capabilities
- registerDONAndCapabilities(t, capRegAddr, hashedCapabilities, nodesInfo, sc)
+ // Log extra information that might help debugging
+ t.Cleanup(func() {
+ if t.Failed() {
+ logTestInfo(testLogger, in.WorkflowConfig.FeedID, in.WorkflowConfig.WorkflowName, feedsConsumerAddress.Hex(), keystoneContractSet.Forwarder.Address().Hex())
+ }
+ })
- // configure Keystone Forwarder contract
- configureKeystoneForwarder(t, forwarderAddress, sc, nodesInfo)
+ // set variables that are needed for the cleanup function, which debugs report transmissions
+ nodes = &ns
+ wsRPCURL = &bc.Nodes[0].HostWSUrl
+ // CAUTION: It is crucial to configure OCR3 jobs on nodes before configuring the workflow contracts.
// Wait for OCR listeners to be ready before setting the configuration.
// If the ConfigSet event is missed, OCR protocol will not start.
// TODO make it fluent!
@@ -1448,8 +1786,8 @@ func TestKeystoneWithOCR3Workflow(t *testing.T) {
time.Sleep(30 * time.Second)
testLogger.Info().Msg("Proceeding to set OCR3 configuration.")
- // Configure OCR3 capability contract
- configureOCR3Capability(t, ocr3CapabilityAddress, sc, nodesInfo)
+ // Configure the workflow DON and contracts
+ configureWorkflowDON(t, ctfEnv, don, chainSelector)
// It can take a while before the first report is produced, particularly on CI.
timeout := 10 * time.Minute
@@ -1459,11 +1797,15 @@ func TestKeystoneWithOCR3Workflow(t *testing.T) {
feedsConsumerInstance, err := feeds_consumer.NewKeystoneFeedsConsumer(feedsConsumerAddress, sc.Client)
require.NoError(t, err, "failed to create feeds consumer instance")
+ testLogger.Info().Msg("Waiting for feed to update...")
startTime := time.Now()
+ feedBytes := common.HexToHash(in.WorkflowConfig.FeedID)
+
for {
select {
case <-ctx.Done():
- t.Fatalf("feed did not update, timeout after %s", timeout)
+ testLogger.Error().Msgf("feed did not update, timeout after %s", timeout)
+ t.FailNow()
case <-time.After(10 * time.Second):
elapsed := time.Since(startTime).Round(time.Second)
price, _, err := feedsConsumerInstance.GetPrice(
diff --git a/integration-tests/smoke/ccip/ccip_add_chain_test.go b/integration-tests/smoke/ccip/ccip_add_chain_test.go
index 0d729b34371..4b634543462 100644
--- a/integration-tests/smoke/ccip/ccip_add_chain_test.go
+++ b/integration-tests/smoke/ccip/ccip_add_chain_test.go
@@ -667,7 +667,7 @@ func feeQuoterDestUpdates(t *testing.T, dests []uint64, sources []uint64) (updat
if _, ok := updates[source]; !ok {
updates[source] = make(map[uint64]fee_quoter.FeeQuoterDestChainConfig)
}
- updates[source][dest] = ccipcs.DefaultFeeQuoterDestChainConfig()
+ updates[source][dest] = ccipcs.DefaultFeeQuoterDestChainConfig(true)
}
}
return
diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go
index 8284fcd2823..71e31e9cd70 100644
--- a/integration-tests/smoke/ccip/ccip_batching_test.go
+++ b/integration-tests/smoke/ccip/ccip_batching_test.go
@@ -27,7 +27,7 @@ import (
)
const (
- numMessages = 25
+ numMessages = 5
)
type batchTestSetup struct {
@@ -71,8 +71,6 @@ func newBatchTestSetup(t *testing.T) batchTestSetup {
}
func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) {
- t.Parallel()
-
ctx := testhelpers.Context(t)
setup := newBatchTestSetup(t)
sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state
@@ -137,10 +135,6 @@ func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) {
}
func Test_CCIPBatching_MultiSource(t *testing.T) {
- // t.Skip("Exec not working, boosting not working correctly")
-
- t.Parallel()
-
// Setup 3 chains, with 2 lanes going to the dest.
ctx := testhelpers.Context(t)
setup := newBatchTestSetup(t)
@@ -266,8 +260,6 @@ func Test_CCIPBatching_MultiSource(t *testing.T) {
}
func Test_CCIPBatching_SingleSource(t *testing.T) {
- t.Parallel()
-
// Setup 3 chains, with 2 lanes going to the dest.
ctx := testhelpers.Context(t)
setup := newBatchTestSetup(t)
diff --git a/integration-tests/smoke/ccip/ccip_disable_lane_test.go b/integration-tests/smoke/ccip/ccip_disable_lane_test.go
new file mode 100644
index 00000000000..6622a6061e9
--- /dev/null
+++ b/integration-tests/smoke/ccip/ccip_disable_lane_test.go
@@ -0,0 +1,142 @@
+package ccip
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
+ "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext"
+ "github.com/smartcontractkit/chainlink/deployment"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
+ "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+ testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
+)
+
+// Intention of this test is to ensure that the lane can be disabled and enabled correctly
+// without disrupting the other lanes and in-flight requests are delivered.
+func TestDisableLane(t *testing.T) {
+ tenv, _, _ := testsetups.NewIntegrationEnvironment(t,
+ testhelpers.WithNumOfChains(3),
+ testhelpers.WithNumOfUsersPerChain(2),
+ )
+
+ e := tenv.Env
+ state, err := changeset.LoadOnchainState(e)
+ require.NoError(t, err)
+
+ // add all lanes
+ testhelpers.AddLanesForAll(t, &tenv, state)
+
+ var (
+ chains = e.AllChainSelectors()
+ chainA, chainB, chainC = chains[0], chains[1], chains[2]
+ expectedSeqNumExec = make(map[testhelpers.SourceDestPair][]uint64)
+ startBlocks = make(map[uint64]*uint64)
+ pairs []testhelpers.SourceDestPair
+ linkPrice = deployment.E18Mult(100)
+ wethPrice = deployment.E18Mult(4000)
+ noOfRequests = 3
+ sendmessage = func(src, dest uint64, deployer *bind.TransactOpts) (*onramp.OnRampCCIPMessageSent, error) {
+ return testhelpers.DoSendRequest(
+ t,
+ e,
+ state,
+ testhelpers.WithSender(deployer),
+ testhelpers.WithSourceChain(src),
+ testhelpers.WithDestChain(dest),
+ testhelpers.WithTestRouter(false),
+ testhelpers.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{
+ Receiver: common.LeftPadBytes(state.Chains[chainB].Receiver.Address().Bytes(), 32),
+ Data: []byte("hello"),
+ TokenAmounts: nil,
+ FeeToken: common.HexToAddress("0x0"),
+ ExtraArgs: nil,
+ }))
+ }
+
+ assertSendRequestReverted = func(src, dest uint64, deployer *bind.TransactOpts) {
+ _, err = sendmessage(src, dest, deployer)
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "execution reverted")
+ }
+
+ assertRequestSent = func(src, dest uint64, deployer *bind.TransactOpts) {
+ latestHeader, err := e.Chains[dest].Client.HeaderByNumber(testcontext.Get(t), nil)
+ require.NoError(t, err)
+ block := latestHeader.Number.Uint64()
+ messageSentEvent, err := sendmessage(src, dest, e.Chains[src].DeployerKey)
+ require.NoError(t, err)
+ expectedSeqNumExec[testhelpers.SourceDestPair{
+ SourceChainSelector: src,
+ DestChainSelector: dest,
+ }] = []uint64{messageSentEvent.SequenceNumber}
+ startBlocks[dest] = &block
+ }
+ )
+
+ // disable lane A -> B
+ pairs = append(pairs, testhelpers.SourceDestPair{
+ SourceChainSelector: chainA,
+ DestChainSelector: chainB,
+ })
+ testhelpers.RemoveLane(t, &tenv, chainA, chainB, false)
+ // send a message to confirm it is reverted between A -> B
+ assertSendRequestReverted(chainA, chainB, e.Chains[chainA].Users[0])
+
+ // send a message in other direction B -> A to confirm it is delivered
+ assertRequestSent(chainB, chainA, e.Chains[chainB].Users[0])
+ testhelpers.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks)
+
+ // send a multiple message between A -> C and disable the lane while the requests are in-flight
+ expectedSeqNumExec = make(map[testhelpers.SourceDestPair][]uint64)
+ for range noOfRequests {
+ assertRequestSent(chainA, chainC, e.Chains[chainA].Users[1])
+ }
+ // disable lane A -> C while requests are getting sent in that lane
+ pairs = append(pairs, testhelpers.SourceDestPair{
+ SourceChainSelector: chainA,
+ DestChainSelector: chainC,
+ })
+ testhelpers.RemoveLane(t, &tenv, chainA, chainC, false)
+
+ // confirm all in-flight messages are delivered in A -> C lane
+ testhelpers.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks)
+
+ // now, as the lane is disabled, confirm that message sent in A -> C is reverted
+ assertSendRequestReverted(chainA, chainC, e.Chains[chainA].Users[0])
+
+ // check getting token and gas price form fee quoter returns error when A -> C lane is disabled
+ gp, err := state.Chains[chainA].FeeQuoter.GetTokenAndGasPrices(&bind.CallOpts{
+ Context: tests.Context(t),
+ }, state.Chains[chainC].Weth9.Address(), chainC)
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "execution reverted")
+ require.Nil(t, gp.GasPriceValue)
+ require.Nil(t, gp.TokenPrice)
+
+ // re-enable all the disabled lanes
+ for _, pair := range pairs {
+ testhelpers.AddLane(t, &tenv, pair.SourceChainSelector, pair.DestChainSelector, false,
+ map[uint64]*big.Int{
+ pair.DestChainSelector: testhelpers.DefaultGasPrice,
+ },
+ map[common.Address]*big.Int{
+ state.Chains[pair.SourceChainSelector].LinkToken.Address(): linkPrice,
+ state.Chains[pair.SourceChainSelector].Weth9.Address(): wethPrice,
+ },
+ changeset.DefaultFeeQuoterDestChainConfig(true))
+ }
+ // send a message in all the lane including re-enabled lanes
+ for _, pair := range pairs {
+ assertRequestSent(pair.SourceChainSelector, pair.DestChainSelector, e.Chains[pair.SourceChainSelector].Users[0])
+ }
+ // confirm all messages are delivered
+ testhelpers.ConfirmExecWithSeqNrsForAll(t, e, state, expectedSeqNumExec, startBlocks)
+}
diff --git a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go
index dbe929fe322..6f4deea8b23 100644
--- a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go
+++ b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go
@@ -80,7 +80,7 @@ func Test_CCIPFeeBoosting(t *testing.T) {
)
t.Log("Adjusted gas price on dest chain:", adjustedGasPriceDest)
- feeQuoterCfg := changeset.DefaultFeeQuoterDestChainConfig()
+ feeQuoterCfg := changeset.DefaultFeeQuoterDestChainConfig(true)
// the default adds 10% to the gas price, we want to increase it
// to make sure the fee boosting will be finished in proper time for testing
feeQuoterCfg.GasMultiplierWeiPerEth = 120e16
diff --git a/integration-tests/smoke/ccip/ccip_fees_test.go b/integration-tests/smoke/ccip/ccip_fees_test.go
index a7872c3930d..db323783cfd 100644
--- a/integration-tests/smoke/ccip/ccip_fees_test.go
+++ b/integration-tests/smoke/ccip/ccip_fees_test.go
@@ -18,8 +18,8 @@ import (
testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/weth9"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/evm/assets"
)
@@ -330,7 +330,7 @@ func runFeeTokenTestCase(tc feeTokenTestCase) {
if tc.feeToken != common.HexToAddress("0x0") {
if tc.feeToken == state.Chains[tc.src].Weth9.Address() {
// Deposit some ETH into the WETH contract
- weth9, err := weth9_wrapper.NewWETH9(state.Chains[tc.src].Weth9.Address(), srcChain.Client)
+ weth9, err := weth9.NewWETH9(state.Chains[tc.src].Weth9.Address(), srcChain.Client)
require.NoError(tc.t, err)
balance, err := srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil)
diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip/ccip_messaging_test.go
index 69900b29322..eb9b4bfd847 100644
--- a/integration-tests/smoke/ccip/ccip_messaging_test.go
+++ b/integration-tests/smoke/ccip/ccip_messaging_test.go
@@ -5,48 +5,23 @@ import (
"fmt"
"math/big"
"testing"
- "time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"golang.org/x/exp/maps"
- chain_selectors "github.com/smartcontractkit/chain-selectors"
-
"github.com/smartcontractkit/chainlink-common/pkg/hashutil"
"github.com/smartcontractkit/chainlink-common/pkg/merklemulti"
- "github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
"github.com/smartcontractkit/chainlink/deployment"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset"
"github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers"
+ mt "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/messagingtest"
testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
- "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router"
)
-type testCaseSetup struct {
- t *testing.T
- sender []byte
- deployedEnv testhelpers.DeployedEnv
- onchainState changeset.CCIPOnChainState
- sourceChain, destChain uint64
-}
-
-type messagingTestCase struct {
- testCaseSetup
- replayed bool
- nonce uint64
-}
-
-type messagingTestCaseOutput struct {
- replayed bool
- nonce uint64
- msgSentEvent *onramp.OnRampCCIPMessageSent
-}
-
func Test_CCIPMessaging(t *testing.T) {
// Setup 2 chains and a single lane.
ctx := testhelpers.Context(t)
@@ -72,65 +47,70 @@ func Test_CCIPMessaging(t *testing.T) {
replayed bool
nonce uint64
sender = common.LeftPadBytes(e.Env.Chains[sourceChain].DeployerKey.From.Bytes(), 32)
- out messagingTestCaseOutput
- setup = testCaseSetup{
- t: t,
- sender: sender,
- deployedEnv: e,
- onchainState: state,
- sourceChain: sourceChain,
- destChain: destChain,
- }
+ out mt.TestCaseOutput
+ setup = mt.NewTestSetupWithDeployedEnv(
+ t,
+ e,
+ state,
+ sourceChain,
+ destChain,
+ sender,
+ false, // testRouter
+ true, // validateResp
+ )
)
t.Run("data message to eoa", func(t *testing.T) {
- out = runMessagingTestCase(messagingTestCase{
- testCaseSetup: setup,
- replayed: replayed,
- nonce: nonce,
- },
- common.HexToAddress("0xdead"),
- []byte("hello eoa"),
- nil, // default extraArgs
- testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA
+ out = mt.Run(
+ mt.TestCase{
+ TestSetup: setup,
+ Replayed: replayed,
+ Nonce: nonce,
+ Receiver: common.HexToAddress("0xdead"),
+ MsgData: []byte("hello eoa"),
+ ExtraArgs: nil, // default extraArgs
+ ExpectedExecutionState: testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA
+ },
)
})
t.Run("message to contract not implementing CCIPReceiver", func(t *testing.T) {
- out = runMessagingTestCase(
- messagingTestCase{
- testCaseSetup: setup,
- replayed: out.replayed,
- nonce: out.nonce,
+ out = mt.Run(
+ mt.TestCase{
+ TestSetup: setup,
+ Replayed: out.Replayed,
+ Nonce: out.Nonce,
+ Receiver: state.Chains[destChain].FeeQuoter.Address(),
+ MsgData: []byte("hello FeeQuoter"),
+ ExtraArgs: nil, // default extraArgs
+ ExpectedExecutionState: testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver
},
- state.Chains[destChain].FeeQuoter.Address(),
- []byte("hello FeeQuoter"),
- nil, // default extraArgs
- testhelpers.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver
)
})
t.Run("message to contract implementing CCIPReceiver", func(t *testing.T) {
latestHead, err := e.Env.Chains[destChain].Client.HeaderByNumber(ctx, nil)
require.NoError(t, err)
- out = runMessagingTestCase(
- messagingTestCase{
- testCaseSetup: setup,
- replayed: out.replayed,
- nonce: out.nonce,
- },
- state.Chains[destChain].Receiver.Address(),
- []byte("hello CCIPReceiver"),
- nil, // default extraArgs
- testhelpers.EXECUTION_STATE_SUCCESS,
- func(t *testing.T) {
- iter, err := state.Chains[destChain].Receiver.FilterMessageReceived(&bind.FilterOpts{
- Context: ctx,
- Start: latestHead.Number.Uint64(),
- })
- require.NoError(t, err)
- require.True(t, iter.Next())
- // MessageReceived doesn't emit the data unfortunately, so can't check that.
+ out = mt.Run(
+ mt.TestCase{
+ TestSetup: setup,
+ Replayed: out.Replayed,
+ Nonce: out.Nonce,
+ Receiver: state.Chains[destChain].Receiver.Address(),
+ MsgData: []byte("hello CCIPReceiver"),
+ ExtraArgs: nil, // default extraArgs
+ ExpectedExecutionState: testhelpers.EXECUTION_STATE_SUCCESS,
+ ExtraAssertions: []func(t *testing.T){
+ func(t *testing.T) {
+ iter, err := state.Chains[destChain].Receiver.FilterMessageReceived(&bind.FilterOpts{
+ Context: ctx,
+ Start: latestHead.Number.Uint64(),
+ })
+ require.NoError(t, err)
+ require.True(t, iter.Next())
+ // MessageReceived doesn't emit the data unfortunately, so can't check that.
+ },
+ },
},
)
})
@@ -138,22 +118,22 @@ func Test_CCIPMessaging(t *testing.T) {
t.Run("message to contract implementing CCIPReceiver with low exec gas", func(t *testing.T) {
latestHead, err := e.Env.Chains[destChain].Client.HeaderByNumber(ctx, nil)
require.NoError(t, err)
- out = runMessagingTestCase(
- messagingTestCase{
- testCaseSetup: setup,
- replayed: out.replayed,
- nonce: out.nonce,
+ out = mt.Run(
+ mt.TestCase{
+ TestSetup: setup,
+ Replayed: out.Replayed,
+ Nonce: out.Nonce,
+ Receiver: state.Chains[destChain].Receiver.Address(),
+ MsgData: []byte("hello CCIPReceiver with low exec gas"),
+ ExtraArgs: testhelpers.MakeEVMExtraArgsV2(1, false), // 1 gas is too low.
+ ExpectedExecutionState: testhelpers.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas
},
- state.Chains[destChain].Receiver.Address(),
- []byte("hello CCIPReceiver with low exec gas"),
- testhelpers.MakeEVMExtraArgsV2(1, false), // 1 gas is too low.
- testhelpers.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas
)
manuallyExecute(ctx, t, latestHead.Number.Uint64(), state, destChain, out, sourceChain, e, sender)
t.Logf("successfully manually executed message %x",
- out.msgSentEvent.Message.Header.MessageId)
+ out.MsgSentEvent.Message.Header.MessageId)
})
}
@@ -163,7 +143,7 @@ func manuallyExecute(
startBlock uint64,
state changeset.CCIPOnChainState,
destChain uint64,
- out messagingTestCaseOutput,
+ out mt.TestCaseOutput,
sourceChain uint64,
e testhelpers.DeployedEnv,
sender []byte,
@@ -172,7 +152,7 @@ func manuallyExecute(
ctx,
t,
state.Chains[destChain].OffRamp,
- out.msgSentEvent.SequenceNumber,
+ out.MsgSentEvent.SequenceNumber,
startBlock,
)
messageHash := getMessageHash(
@@ -180,8 +160,8 @@ func manuallyExecute(
t,
state.Chains[destChain].OffRamp,
sourceChain,
- out.msgSentEvent.SequenceNumber,
- out.msgSentEvent.Message.Header.MessageId,
+ out.MsgSentEvent.SequenceNumber,
+ out.MsgSentEvent.Message.Header.MessageId,
startBlock,
)
tree, err := merklemulti.NewTree(hashutil.NewKeccak(), [][32]byte{messageHash})
@@ -198,11 +178,11 @@ func manuallyExecute(
Messages: []offramp.InternalAny2EVMRampMessage{
{
Header: offramp.InternalRampMessageHeader{
- MessageId: out.msgSentEvent.Message.Header.MessageId,
+ MessageId: out.MsgSentEvent.Message.Header.MessageId,
SourceChainSelector: sourceChain,
DestChainSelector: destChain,
- SequenceNumber: out.msgSentEvent.SequenceNumber,
- Nonce: out.msgSentEvent.Message.Header.Nonce,
+ SequenceNumber: out.MsgSentEvent.SequenceNumber,
+ Nonce: out.MsgSentEvent.Message.Header.Nonce,
},
Sender: sender,
Data: []byte("hello CCIPReceiver with low exec gas"),
@@ -230,7 +210,7 @@ func manuallyExecute(
_, err = deployment.ConfirmIfNoError(e.Env.Chains[destChain], tx, err)
require.NoError(t, err, "failed to send/confirm manuallyExecute tx")
- newExecutionState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, out.msgSentEvent.SequenceNumber)
+ newExecutionState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, out.MsgSentEvent.SequenceNumber)
require.NoError(t, err)
require.Equal(t, uint8(testhelpers.EXECUTION_STATE_SUCCESS), newExecutionState)
}
@@ -288,106 +268,6 @@ func getMessageHash(
return iter.Event.MessageHash
}
-func sleepAndReplay(t *testing.T, e testhelpers.DeployedEnv, sourceChain, destChain uint64) {
- time.Sleep(30 * time.Second)
- replayBlocks := make(map[uint64]uint64)
- replayBlocks[sourceChain] = 1
- replayBlocks[destChain] = 1
- testhelpers.ReplayLogs(t, e.Env.Offchain, replayBlocks)
-}
-
-func getLatestNonce(tc messagingTestCase) uint64 {
- family, err := chain_selectors.GetSelectorFamily(tc.destChain)
- require.NoError(tc.t, err)
-
- var latestNonce uint64
- switch family {
- case chain_selectors.FamilyEVM:
- latestNonce, err = tc.onchainState.Chains[tc.destChain].NonceManager.GetInboundNonce(&bind.CallOpts{
- Context: tests.Context(tc.t),
- }, tc.sourceChain, tc.sender)
- require.NoError(tc.t, err)
- case chain_selectors.FamilySolana:
- // var nonceCounterAccount ccip_router.Nonce
- // err = common.GetAccountDataBorshInto(ctx, solanaGoClient, nonceEvmPDA, config.DefaultCommitment, &nonceCounterAccount)
- // require.NoError(t, err, "failed to get account info")
- // require.Equal(t, uint64(1), nonceCounterAccount.Counter)
- }
- return latestNonce
-}
-
-func runMessagingTestCase(
- tc messagingTestCase,
- receiver common.Address,
- msgData []byte,
- extraArgs []byte,
- expectedExecutionState int,
- extraAssertions ...func(t *testing.T),
-) (out messagingTestCaseOutput) {
- // check latest nonce
- latestNonce := getLatestNonce(tc)
- require.Equal(tc.t, tc.nonce, latestNonce)
-
- startBlocks := make(map[uint64]*uint64)
- msgSentEvent := testhelpers.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{
- Receiver: common.LeftPadBytes(receiver.Bytes(), 32),
- Data: msgData,
- TokenAmounts: nil,
- FeeToken: common.HexToAddress("0x0"),
- ExtraArgs: extraArgs,
- })
- expectedSeqNum := map[testhelpers.SourceDestPair]uint64{
- {
- SourceChainSelector: tc.sourceChain,
- DestChainSelector: tc.destChain,
- }: msgSentEvent.SequenceNumber,
- }
- expectedSeqNumExec := map[testhelpers.SourceDestPair][]uint64{
- {
- SourceChainSelector: tc.sourceChain,
- DestChainSelector: tc.destChain,
- }: {msgSentEvent.SequenceNumber},
- }
- out.msgSentEvent = msgSentEvent
-
- // hack
- if !tc.replayed {
- sleepAndReplay(tc.t, tc.deployedEnv, tc.sourceChain, tc.destChain)
- out.replayed = true
- }
-
- testhelpers.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks)
- execStates := testhelpers.ConfirmExecWithSeqNrsForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNumExec, startBlocks)
-
- require.Equalf(
- tc.t,
- expectedExecutionState,
- execStates[testhelpers.SourceDestPair{
- SourceChainSelector: tc.sourceChain,
- DestChainSelector: tc.destChain,
- }][msgSentEvent.SequenceNumber],
- "wrong execution state for seq nr %d, expected %d, got %d",
- msgSentEvent.SequenceNumber,
- expectedExecutionState,
- execStates[testhelpers.SourceDestPair{
- SourceChainSelector: tc.sourceChain,
- DestChainSelector: tc.destChain,
- }][msgSentEvent.SequenceNumber],
- )
-
- // check the sender latestNonce on the dest, should be incremented
- latestNonce = getLatestNonce(tc)
- require.Equal(tc.t, tc.nonce+1, latestNonce)
- out.nonce = latestNonce
- tc.t.Logf("confirmed nonce bump for sender %x, latestNonce %d", tc.sender, latestNonce)
-
- for _, assertion := range extraAssertions {
- assertion(tc.t)
- }
-
- return
-}
-
// boolsToBitFlags transforms a list of boolean flags to a *big.Int encoded number.
func boolsToBitFlags(bools []bool) *big.Int {
encodedFlags := big.NewInt(0)
diff --git a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go
index 1e0a8fc82f7..bab7717f3b1 100644
--- a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go
+++ b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go
@@ -25,6 +25,9 @@ import (
)
func TestMigrateFromV1_5ToV1_6(t *testing.T) {
+ t.Skipf("Skipping test due to flakiness. " +
+ "This test getting face lifted in this ticket CCIP-4883 and will resolve the flakiness part of it.")
+
// Deploy CCIP 1.5 with 3 chains and 4 nodes + 1 bootstrap
// Deploy 1.5 contracts (excluding pools to start, but including MCMS) .
e, _, tEnv := testsetups.NewIntegrationEnvironment(
diff --git a/integration-tests/smoke/ccip/ccip_reader_test.go b/integration-tests/smoke/ccip/ccip_reader_test.go
index 1c7803bf443..c0126a5dc5e 100644
--- a/integration-tests/smoke/ccip/ccip_reader_test.go
+++ b/integration-tests/smoke/ccip/ccip_reader_test.go
@@ -44,6 +44,8 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp"
"github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract"
+ "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote"
"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"
@@ -98,7 +100,7 @@ func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityD
return s, finalityDepth, onRampAddress
}
-func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData {
+func setupExecutedMessagesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData {
sb, auth := setupSimulatedBackendAndAuth(t)
return testSetup(ctx, t, testSetupParams{
ReaderChain: chainD,
@@ -182,6 +184,120 @@ func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numR
return firstReportTs
}
+func TestCCIPReader_GetRMNRemoteConfig(t *testing.T) {
+ t.Parallel()
+ ctx := tests.Context(t)
+ sb, auth := setupSimulatedBackendAndAuth(t)
+
+ rmnRemoteAddr, _, _, err := rmn_remote.DeployRMNRemote(auth, sb.Client(), uint64(chainD), utils.RandomAddress())
+ require.NoError(t, err)
+ sb.Commit()
+
+ proxyAddr, _, _, err := rmn_proxy_contract.DeployRMNProxy(auth, sb.Client(), rmnRemoteAddr)
+ require.NoError(t, err)
+ sb.Commit()
+
+ t.Logf("Proxy address: %s, rmn remote address: %s", proxyAddr.Hex(), rmnRemoteAddr.Hex())
+
+ proxy, err := rmn_proxy_contract.NewRMNProxy(proxyAddr, sb.Client())
+ require.NoError(t, err)
+
+ currARM, err := proxy.GetARM(&bind.CallOpts{
+ Context: ctx,
+ })
+ require.NoError(t, err)
+ require.Equal(t, currARM, rmnRemoteAddr)
+
+ rmnRemote, err := rmn_remote.NewRMNRemote(rmnRemoteAddr, sb.Client())
+ require.NoError(t, err)
+
+ _, err = rmnRemote.SetConfig(auth, rmn_remote.RMNRemoteConfig{
+ RmnHomeContractConfigDigest: utils.RandomBytes32(),
+ Signers: []rmn_remote.RMNRemoteSigner{
+ {
+ OnchainPublicKey: utils.RandomAddress(),
+ NodeIndex: 0,
+ },
+ {
+ OnchainPublicKey: utils.RandomAddress(),
+ NodeIndex: 1,
+ },
+ {
+ OnchainPublicKey: utils.RandomAddress(),
+ NodeIndex: 2,
+ },
+ },
+ FSign: 1, // 2*FSign + 1 == 3
+ })
+ require.NoError(t, err)
+ sb.Commit()
+
+ db := pgtest.NewSqlxDB(t)
+ lggr := logger.TestLogger(t)
+ lggr.SetLogLevel(zapcore.ErrorLevel)
+ lpOpts := logpoller.Opts{
+ PollPeriod: time.Millisecond,
+ FinalityDepth: 1,
+ BackfillBatchSize: 10,
+ RpcBatchSize: 10,
+ KeepFinalizedBlocksDepth: 100000,
+ }
+ cl := client.NewSimulatedBackendClient(t, sb, big.NewInt(1337))
+ headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth)
+ orm := logpoller.NewORM(big.NewInt(1337), db, lggr)
+ lp := logpoller.NewLogPoller(
+ orm,
+ cl,
+ lggr,
+ headTracker,
+ lpOpts,
+ )
+ require.NoError(t, lp.Start(ctx))
+ t.Cleanup(func() { require.NoError(t, lp.Close()) })
+
+ cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, evmconfig.DestReaderConfig)
+ require.NoError(t, err)
+ err = cr.Start(ctx)
+ require.NoError(t, err)
+ t.Cleanup(func() { require.NoError(t, cr.Close()) })
+
+ extendedCr := contractreader.NewExtendedContractReader(cr)
+ err = extendedCr.Bind(ctx, []types.BoundContract{
+ {
+ Address: proxyAddr.String(),
+ Name: consts.ContractNameRMNRemote,
+ },
+ })
+ require.NoError(t, err)
+
+ reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(
+ ctx,
+ lggr,
+ map[cciptypes.ChainSelector]contractreader.Extended{
+ chainD: extendedCr,
+ },
+ nil,
+ chainD,
+ rmnRemoteAddr.Bytes(),
+ ccipcommon.NewExtraDataCodec(),
+ )
+
+ exp, err := rmnRemote.GetVersionedConfig(&bind.CallOpts{
+ Context: ctx,
+ })
+ require.NoError(t, err)
+
+ rmnRemoteConfig, err := reader.GetRMNRemoteConfig(ctx)
+ require.NoError(t, err)
+ require.Equal(t, exp.Config.RmnHomeContractConfigDigest[:], rmnRemoteConfig.ConfigDigest[:])
+ require.Equal(t, len(exp.Config.Signers), len(rmnRemoteConfig.Signers))
+ for i, signer := range exp.Config.Signers {
+ require.Equal(t, signer.OnchainPublicKey.Bytes(), []byte(rmnRemoteConfig.Signers[i].OnchainPublicKey))
+ require.Equal(t, signer.NodeIndex, rmnRemoteConfig.Signers[i].NodeIndex)
+ }
+ require.Equal(t, exp.Config.FSign, rmnRemoteConfig.FSign)
+}
+
func TestCCIPReader_GetOffRampConfigDigest(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
@@ -319,7 +435,6 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) {
require.Eventually(t, func() bool {
reports, err = s.reader.CommitReportsGTETimestamp(
ctx,
- chainD,
// Skips first report
//nolint:gosec // this won't overflow
time.Unix(int64(firstReportTs)+1, 0),
@@ -364,7 +479,6 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) {
require.Never(t, func() bool {
reports, err = s.reader.CommitReportsGTETimestamp(
ctx,
- chainD,
// Skips first report
//nolint:gosec // this won't overflow
time.Unix(int64(firstReportTs)+1, 0),
@@ -382,7 +496,6 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) {
require.Eventually(t, func() bool {
reports, err = s.reader.CommitReportsGTETimestamp(
ctx,
- chainD,
// Skips first report
//nolint:gosec // this won't overflow
time.Unix(int64(firstReportTs)+1, 0),
@@ -406,10 +519,10 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) {
assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64())
}
-func TestCCIPReader_ExecutedMessageRanges(t *testing.T) {
+func TestCCIPReader_ExecutedMessages(t *testing.T) {
t.Parallel()
ctx := tests.Context(t)
- s := setupExecutedMessageRangesTest(ctx, t, false)
+ s := setupExecutedMessagesTest(ctx, t, false)
_, err := s.contract.EmitExecutionStateChanged(
s.auth,
uint64(chainS1),
@@ -440,23 +553,18 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) {
// Maybe another situation where chain reader doesn't register filters as expected.
require.NoError(t, s.lp.Replay(ctx, 1))
- var executedRanges []cciptypes.SeqNumRange
+ var executedMsgs []cciptypes.SeqNum
require.Eventually(t, func() bool {
- executedRanges, err = s.reader.ExecutedMessageRanges(
+ executedMsgs, err = s.reader.ExecutedMessages(
ctx,
chainS1,
- chainD,
cciptypes.NewSeqNumRange(14, 15),
)
require.NoError(t, err)
- return len(executedRanges) == 2
+ return len(executedMsgs) == 2
}, tests.WaitTimeout(t), 50*time.Millisecond)
- assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start())
- assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End())
-
- assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start())
- assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End())
+ assert.Equal(t, []cciptypes.SeqNum{14, 15}, executedMsgs)
}
func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) {
@@ -623,7 +731,7 @@ func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) {
msgSentEvent := testhelpers.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg)
require.Equal(t, uint64(i), msgSentEvent.SequenceNumber)
require.Equal(t, uint64(i), msgSentEvent.Message.Header.Nonce) // check outbound nonce incremented
- seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain), cs(destChain))
+ seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain))
require.NoError(t, err2)
require.Equal(t, cciptypes.SeqNum(i+1), seqNum)
}
@@ -688,7 +796,7 @@ func TestCCIPReader_Nonces(t *testing.T) {
}
addrQuery = append(addrQuery, utils.RandomAddress().String())
- results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery)
+ results, err := s.reader.Nonces(ctx, sourceChain, addrQuery)
require.NoError(t, err)
assert.Len(t, results, len(addrQuery))
for addr, nonce := range addrs {
@@ -805,7 +913,7 @@ func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) {
boundContracts := map[cciptypes.ChainSelector][]types.BoundContract{}
for i, selector := range env.Env.AllChainSelectorsExcluding([]uint64{destChain}) {
feeQuoter := state.Chains[selector].FeeQuoter
- destChainCfg := changeset.DefaultFeeQuoterDestChainConfig()
+ destChainCfg := changeset.DefaultFeeQuoterDestChainConfig(true)
//nolint:gosec // disable G115
destChainCfg.DestDataAvailabilityOverheadGas = uint32(100 + i)
//nolint:gosec // disable G115
@@ -929,7 +1037,7 @@ func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMat
b.ResetTimer()
for i := 0; i < b.N; i++ {
- reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst)
+ reports, err := s.reader.CommitReportsGTETimestamp(ctx, queryTimestamp, logsInsertedFirst)
require.NoError(b, err)
require.Len(b, reports, logsInsertedFirst)
}
@@ -1022,12 +1130,12 @@ func populateDatabaseForCommitReportAccepted(
}
// Benchmark Results:
-// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op
-// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op
-// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op
-// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op
-// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op
-func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) {
+// Benchmark_CCIPReader_ExecutedMessages/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op
+// Benchmark_CCIPReader_ExecutedMessages/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op
+// Benchmark_CCIPReader_ExecutedMessages/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op
+// Benchmark_CCIPReader_ExecutedMessages/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op
+// Benchmark_CCIPReader_ExecutedMessages/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op
+func Benchmark_CCIPReader_ExecutedMessages(b *testing.B) {
tests := []struct {
logsInserted int
startSeqNum cciptypes.SeqNum
@@ -1042,15 +1150,15 @@ func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) {
for _, tt := range tests {
b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) {
- benchmarkExecutedMessageRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum)
+ benchmarkExecutedMessages(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum)
})
}
}
-func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) {
+func benchmarkExecutedMessages(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) {
// Initialize test setup
ctx := tests.Context(b)
- s := setupExecutedMessageRangesTest(ctx, b, true)
+ s := setupExecutedMessagesTest(ctx, b, true)
expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum)
// Insert logs in two phases based on parameters
@@ -1062,10 +1170,9 @@ func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSe
b.ResetTimer()
for i := 0; i < b.N; i++ {
- executedRanges, err := s.reader.ExecutedMessageRanges(
+ executedRanges, err := s.reader.ExecutedMessages(
ctx,
chainS1,
- chainD,
cciptypes.NewSeqNumRange(startSeqNum, endSeqNum),
)
require.NoError(b, err)
diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go
index 5b82b08854d..4a9bd90f0d1 100644
--- a/integration-tests/testsetups/ccip/test_helpers.go
+++ b/integration-tests/testsetups/ccip/test_helpers.go
@@ -719,3 +719,18 @@ func SetNodeConfig(nets []blockchain.EVMNetwork, nodeConfig, commonChain string,
tomlStr, err := tomlCfg.TOMLString()
return tomlCfg, tomlStr, err
}
+
+func GetSourceDestPairs(chains []uint64) []testhelpers.SourceDestPair {
+ var pairs []testhelpers.SourceDestPair
+ for i, src := range chains {
+ for j, dest := range chains {
+ if i != j {
+ pairs = append(pairs, testhelpers.SourceDestPair{
+ SourceChainSelector: src,
+ DestChainSelector: dest,
+ })
+ }
+ }
+ }
+ return pairs
+}
diff --git a/internal/testdb/testdb.go b/internal/testdb/testdb.go
index 88664e87f99..64c04c01908 100644
--- a/internal/testdb/testdb.go
+++ b/internal/testdb/testdb.go
@@ -1,13 +1,10 @@
package testdb
import (
- "database/sql"
- "errors"
- "fmt"
"net/url"
- "strings"
+ "testing"
- pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg"
+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest"
)
const (
@@ -20,62 +17,12 @@ const (
// CreateOrReplace creates a database named with a common prefix and the given suffix, and returns the URL.
// If the database already exists, it will be dropped and re-created.
// If withTemplate is true, the pristine DB will be used as a template.
-func CreateOrReplace(parsed url.URL, suffix string, withTemplate bool) (string, error) {
- if parsed.Path == "" {
- return "", errors.New("path missing from database URL")
- }
-
+func CreateOrReplace(t testing.TB, parsed url.URL, suffix string, withTemplate bool) url.URL {
// Match the naming schema that our dangling DB cleanup methods expect
dbname := TestDBNamePrefix + suffix
- if l := len(dbname); l > 63 {
- return "", fmt.Errorf("dbname %v too long (%d), max is 63 bytes. Try a shorter suffix", dbname, l)
- }
- // Cannot drop test database if we are connected to it, so we must connect
- // to a different one. 'postgres' should be present on all postgres installations
- parsed.Path = "/postgres"
- db, err := sql.Open(pgcommon.DriverPostgres, parsed.String())
- if err != nil {
- return "", fmt.Errorf("in order to drop the test database, we need to connect to a separate database"+
- " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err)
- }
- defer db.Close()
-
- _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", dbname))
- if err != nil {
- return "", fmt.Errorf("unable to drop postgres migrations test database: %v", err)
- }
+ var template string
if withTemplate {
- _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s WITH TEMPLATE %s", dbname, PristineDBName))
- } else {
- _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbname))
- }
- if err != nil {
- return "", fmt.Errorf("unable to create postgres test database with name '%s': %v", dbname, err)
- }
- parsed.Path = fmt.Sprintf("/%s", dbname)
- return parsed.String(), nil
-}
-
-// Drop drops the database at the given URL.
-func Drop(dbURL url.URL) error {
- if dbURL.Path == "" {
- return errors.New("path missing from database URL")
- }
- dbname := strings.TrimPrefix(dbURL.Path, "/")
-
- // Cannot drop test database if we are connected to it, so we must connect
- // to a different one. 'postgres' should be present on all postgres installations
- dbURL.Path = "/postgres"
- db, err := sql.Open(pgcommon.DriverPostgres, dbURL.String())
- if err != nil {
- return fmt.Errorf("in order to drop the test database, we need to connect to a separate database"+
- " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err)
- }
- defer db.Close()
-
- _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", dbname))
- if err != nil {
- return fmt.Errorf("unable to drop postgres migrations test database: %v", err)
+ template = PristineDBName
}
- return nil
+ return sqltest.CreateOrReplace(t, parsed, dbname, template)
}
diff --git a/main_test.go b/main_test.go
index f5efe1a2957..a4984e3f7b7 100644
--- a/main_test.go
+++ b/main_test.go
@@ -60,7 +60,7 @@ func TestScripts(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: path,
- Setup: commonEnv,
+ Setup: commonEnv(t),
ContinueOnError: true,
// UpdateScripts: true, // uncomment to update golden files
})
@@ -74,47 +74,46 @@ func TestScripts(t *testing.T) {
// isIntegrationBuild is toggled true by a func init() with a //go:build integration gate
var isIntegrationBuild = false
-func commonEnv(te *testscript.Env) error {
- if _, err := os.Stat(integrationBuildName); err == nil && !isIntegrationBuild {
- te.T().Skip("integration test")
- return nil
- }
+func commonEnv(t testing.TB) func(*testscript.Env) error {
+ return func(te *testscript.Env) error {
+ if _, err := os.Stat(integrationBuildName); err == nil && !isIntegrationBuild {
+ te.T().Skip("integration test")
+ return nil
+ }
- te.Setenv("HOME", "$WORK/home")
- te.Setenv("VERSION", static.Version)
- te.Setenv("COMMIT_SHA", static.Sha)
+ te.Setenv("HOME", "$WORK/home")
+ te.Setenv("VERSION", static.Version)
+ te.Setenv("COMMIT_SHA", static.Sha)
- b, err := os.ReadFile(filepath.Join(te.WorkDir, testPortName))
- if err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("failed to read file %s: %w", testPortName, err)
- } else if err == nil {
- envVarName := strings.TrimSpace(string(b))
- te.T().Log("test port requested:", envVarName)
+ b, err := os.ReadFile(filepath.Join(te.WorkDir, testPortName))
+ if err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("failed to read file %s: %w", testPortName, err)
+ } else if err == nil {
+ envVarName := strings.TrimSpace(string(b))
+ te.T().Log("test port requested:", envVarName)
- port, ret, err2 := takeFreePort()
- if err2 != nil {
- return err2
+ port, ret, err2 := takeFreePort()
+ if err2 != nil {
+ return err2
+ }
+ te.Defer(ret)
+
+ te.Setenv(envVarName, strconv.Itoa(port))
}
- te.Defer(ret)
- te.Setenv(envVarName, strconv.Itoa(port))
- }
+ b, err = os.ReadFile(filepath.Join(te.WorkDir, testDBName))
+ if err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("failed to read file %s: %w", testDBName, err)
+ } else if err == nil {
+ envVarName := strings.TrimSpace(string(b))
+ te.T().Log("test database requested:", envVarName)
- b, err = os.ReadFile(filepath.Join(te.WorkDir, testDBName))
- if err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("failed to read file %s: %w", testDBName, err)
- } else if err == nil {
- envVarName := strings.TrimSpace(string(b))
- te.T().Log("test database requested:", envVarName)
+ u2 := newDB(t)
- u2, err2 := initDB()
- if err2 != nil {
- return err2
+ te.Setenv(envVarName, u2)
}
-
- te.Setenv(envVarName, u2)
+ return nil
}
- return nil
}
func takeFreePort() (int, func(), error) {
@@ -125,16 +124,13 @@ func takeFreePort() (int, func(), error) {
return ports[0], func() { freeport.Return(ports) }, nil
}
-func initDB() (string, error) {
+func newDB(t testing.TB) string {
u, err := url.Parse(string(env.DatabaseURL.Get()))
if err != nil {
- return "", fmt.Errorf("failed to parse url: %w", err)
+ t.Fatalf("failed to parse url: %v", err)
}
name := strings.ReplaceAll(uuid.NewString(), "-", "_") + "_test"
- u2, err := testdb.CreateOrReplace(*u, name, true)
- if err != nil {
- return "", fmt.Errorf("failed to create DB: %w", err)
- }
- return u2, nil
+ u2 := testdb.CreateOrReplace(t, *u, name, true)
+ return u2.String()
}
diff --git a/package.json b/package.json
index 8a0b5a3ed5d..465595a3c9d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "chainlink",
- "version": "2.19.0",
+ "version": "2.20.0",
"description": "node of the decentralized oracle network, bridging on and off-chain computation",
"main": "index.js",
"scripts": {
diff --git a/shell.nix b/shell.nix
index 45356a8e189..496559b3cce 100644
--- a/shell.nix
+++ b/shell.nix
@@ -17,13 +17,11 @@ with pkgs; let
inherit name;
url = "https://github.com/anza-xyz/agave/releases/download/${version}/${filename}";
- nativeBuildInputs = [
- autoPatchelfHook
- ];
+ nativeBuildInputs = lib.optionals stdenv.isLinux [ autoPatchelfHook ];
- autoPatchelfIgnoreMissingDeps = true;
+ autoPatchelfIgnoreMissingDeps = stdenv.isLinux;
- buildInputs = with pkgs; [stdenv.cc.cc.libgcc stdenv.cc.cc.lib] ++ lib.optionals stdenv.isLinux [ libudev-zero ];
+ buildInputs = with pkgs; [stdenv.cc.cc.lib] ++ lib.optionals stdenv.isLinux [ stdenv.cc.cc.libgcc libudev-zero ];
src = pkgs.fetchzip {
inherit url sha256;