From 050b3c00594093a9f04f58a394b11b77ecafc423 Mon Sep 17 00:00:00 2001 From: "Abdelrahman Soliman (Boda)" <2677789+asoliman92@users.noreply.github.com> Date: Thu, 20 Jun 2024 17:34:00 +0400 Subject: [PATCH 1/8] Add TokenPricesReader implementation (#1013) Add TokenPricesReader implementation for use in ocr3 --- .changeset/chilled-papayas-chew.md | 5 + .../ocr3/plugins/ccip/commit/factory.go | 13 ++- core/services/ocr3/plugins/ccip/go.mod | 5 +- core/services/ocr3/plugins/ccip/go.sum | 64 +--------- .../ccip/internal/mocks/contract_reader.go | 59 ++++++++++ .../internal/reader/onchain_prices_reader.go | 66 +++++++++++ .../reader/onchain_prices_reader_test.go | 109 ++++++++++++++++++ 7 files changed, 254 insertions(+), 67 deletions(-) create mode 100644 .changeset/chilled-papayas-chew.md create mode 100644 core/services/ocr3/plugins/ccip/internal/mocks/contract_reader.go create mode 100644 core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader.go create mode 100644 core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader_test.go diff --git a/.changeset/chilled-papayas-chew.md b/.changeset/chilled-papayas-chew.md new file mode 100644 index 0000000000..0cd5f6c6e5 --- /dev/null +++ b/.changeset/chilled-papayas-chew.md @@ -0,0 +1,5 @@ +--- +"ccip": patch +--- + +#updated Add TokenPricesReader implementation diff --git a/core/services/ocr3/plugins/ccip/commit/factory.go b/core/services/ocr3/plugins/ccip/commit/factory.go index bf366a0789..6526a03914 100644 --- a/core/services/ocr3/plugins/ccip/commit/factory.go +++ b/core/services/ocr3/plugins/ccip/commit/factory.go @@ -2,12 +2,16 @@ package commit import ( "context" + "math/big" + + "github.com/smartcontractkit/ccipocr3/internal/reader" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "google.golang.org/grpc" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) // PluginFactoryConstructor implements common OCR3ReportingPluginClient and is used for initializing a plugin factory @@ -44,12 +48,19 @@ func NewPluginFactory() *PluginFactory { func (p PluginFactory) NewReportingPlugin(config ocr3types.ReportingPluginConfig, ) (ocr3types.ReportingPlugin[[]byte], ocr3types.ReportingPluginInfo, error) { + onChainTokenPricesReader := reader.NewOnchainTokenPricesReader( + reader.TokenPriceConfig{ // TODO: Inject config + StaticPrices: map[ocr2types.Account]big.Int{}, + }, + nil, // TODO: Inject this + ) + return NewPlugin( context.Background(), config.OracleID, cciptypes.CommitPluginConfig{}, nil, - nil, + onChainTokenPricesReader, nil, nil, nil, diff --git a/core/services/ocr3/plugins/ccip/go.mod b/core/services/ocr3/plugins/ccip/go.mod index 6cb450fe48..0744a0f703 100644 --- a/core/services/ocr3/plugins/ccip/go.mod +++ b/core/services/ocr3/plugins/ccip/go.mod @@ -9,7 +9,6 @@ require ( github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.24.0 golang.org/x/sync v0.7.0 - gonum.org/v1/gonum v0.15.0 google.golang.org/grpc v1.64.0 ) @@ -19,11 +18,9 @@ require ( github.com/buger/jsonparser v1.1.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -40,10 +37,10 @@ require ( github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/core/services/ocr3/plugins/ccip/go.sum b/core/services/ocr3/plugins/ccip/go.sum index 173d9628a8..27321e1eb3 100644 --- a/core/services/ocr3/plugins/ccip/go.sum +++ b/core/services/ocr3/plugins/ccip/go.sum @@ -4,28 +4,16 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= @@ -37,15 +25,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -53,38 +36,20 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ= -github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240605111734-a7c799eab2d7 h1:TUAAjNTJmEmcoG9ZYd4lJrf351iiGQqmuyc79k+3e5E= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240605111734-a7c799eab2d7/go.mod h1:DUZccDEW98n+J1mhdWGO7wr/Njad9p9Fzks839JN7Rs= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613123008-18cccaa4a047 h1:Uxa3A2MwSL8PBc03FPz2U59KOPLYFtTPST8x+jpyHlc= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613123008-18cccaa4a047/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613180521-567f19a341f6 h1:Fd43AdKi57Iobe/+Akua/bU8fsZKtWsBJCePY0Paakw= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613180521-567f19a341f6/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613201342-a855825f87bb h1:R4OkRLPz6mZm8k7JFfLpQ9Ib/e1n1qcxg+hVxc0pKOk= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240613201342-a855825f87bb/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= @@ -101,53 +66,28 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 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= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/core/services/ocr3/plugins/ccip/internal/mocks/contract_reader.go b/core/services/ocr3/plugins/ccip/internal/mocks/contract_reader.go new file mode 100644 index 0000000000..cf3179195d --- /dev/null +++ b/core/services/ocr3/plugins/ccip/internal/mocks/contract_reader.go @@ -0,0 +1,59 @@ +package mocks + +import ( + "context" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/stretchr/testify/mock" +) + +type ContractReaderMock struct { + *mock.Mock +} + +func NewContractReaderMock() *ContractReaderMock { + return &ContractReaderMock{ + Mock: &mock.Mock{}, + } +} + +// GetLatestValue Returns given configs at initialization +func (hr *ContractReaderMock) GetLatestValue(ctx context.Context, contractName, method string, params, returnVal any) error { + args := hr.Called(ctx, contractName, method, params, returnVal) + return args.Error(0) +} + +func (hr *ContractReaderMock) Bind(ctx context.Context, bindings []types.BoundContract) error { + args := hr.Called(ctx, bindings) + return args.Error(0) +} + +func (hr *ContractReaderMock) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]types.Sequence, error) { + args := hr.Called(ctx, contractName, filter, limitAndSort, sequenceDataType) + return args.Get(0).([]types.Sequence), args.Error(1) +} + +func (hr *ContractReaderMock) Start(ctx context.Context) error { + args := hr.Called(ctx) + return args.Error(0) +} + +func (hr *ContractReaderMock) Close() error { + args := hr.Called() + return args.Error(0) +} + +func (hr *ContractReaderMock) Ready() error { + args := hr.Called() + return args.Error(0) +} + +func (hr *ContractReaderMock) HealthReport() map[string]error { + args := hr.Called() + return args.Get(0).(map[string]error) +} + +func (hr *ContractReaderMock) Name() string { + return "ContractReaderMock" +} diff --git a/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader.go b/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader.go new file mode 100644 index 0000000000..707a42ed43 --- /dev/null +++ b/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader.go @@ -0,0 +1,66 @@ +package reader + +import ( + "context" + "fmt" + "math/big" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "golang.org/x/sync/errgroup" +) + +type TokenPriceConfig struct { + // This is mainly used for inputTokens on testnet to give them a price + StaticPrices map[ocr2types.Account]big.Int `json:"staticPrices"` +} + +type OnchainTokenPricesReader struct { + TokenPriceConfig TokenPriceConfig + // Reader for the chain that will have the token prices on-chain + ContractReader commontypes.ContractReader +} + +func NewOnchainTokenPricesReader(tokenPriceConfig TokenPriceConfig, contractReader commontypes.ContractReader) *OnchainTokenPricesReader { + return &OnchainTokenPricesReader{ + TokenPriceConfig: tokenPriceConfig, + ContractReader: contractReader, + } +} + +func (pr *OnchainTokenPricesReader) GetTokenPricesUSD(ctx context.Context, tokens []ocr2types.Account) ([]*big.Int, error) { + const ( + contractName = "PriceAggregator" + functionName = "getTokenPrice" + ) + prices := make([]*big.Int, len(tokens)) + eg := new(errgroup.Group) + for idx, token := range tokens { + idx := idx + token := token + eg.Go(func() error { + price := new(big.Int) + if staticPrice, exists := pr.TokenPriceConfig.StaticPrices[token]; exists { + price.Set(&staticPrice) + } else { + if err := pr.ContractReader.GetLatestValue(ctx, contractName, functionName, token, price); err != nil { + return fmt.Errorf("failed to get token price for %s: %w", token, err) + } + } + prices[idx] = price + return nil + }) + } + + if err := eg.Wait(); err != nil { + return nil, fmt.Errorf("failed to get all token prices successfully: %w", err) + } + + for _, price := range prices { + if price == nil { + return nil, fmt.Errorf("failed to get all token prices successfully, some prices are nil") + } + } + + return prices, nil +} diff --git a/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader_test.go b/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader_test.go new file mode 100644 index 0000000000..e65613d2f4 --- /dev/null +++ b/core/services/ocr3/plugins/ccip/internal/reader/onchain_prices_reader_test.go @@ -0,0 +1,109 @@ +package reader + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/smartcontractkit/ccipocr3/internal/mocks" + + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +const ( + EthAcc = ocr2types.Account("ETH") + OpAcc = ocr2types.Account("OP") + ArbAcc = ocr2types.Account("ARB") +) + +var ( + EthPrice = big.NewInt(100) + OpPrice = big.NewInt(10) + ArbPrice = big.NewInt(1) +) + +func TestOnchainTokenPricesReader_GetTokenPricesUSD(t *testing.T) { + testCases := []struct { + name string + staticPrices map[ocr2types.Account]big.Int + inputTokens []ocr2types.Account + mockPrices map[ocr2types.Account]*big.Int + want []*big.Int + errorAccounts []ocr2types.Account + wantErr bool + }{ + { + name: "Static price only", + staticPrices: map[ocr2types.Account]big.Int{EthAcc: *EthPrice, OpAcc: *OpPrice}, + inputTokens: []ocr2types.Account{EthAcc, OpAcc}, + mockPrices: map[ocr2types.Account]*big.Int{}, + want: []*big.Int{EthPrice, OpPrice}, + }, + { + name: "On-chain price only", + staticPrices: map[ocr2types.Account]big.Int{}, + inputTokens: []ocr2types.Account{ArbAcc, OpAcc, EthAcc}, + mockPrices: map[ocr2types.Account]*big.Int{OpAcc: OpPrice, ArbAcc: ArbPrice, EthAcc: EthPrice}, + want: []*big.Int{ArbPrice, OpPrice, EthPrice}, + }, + { + name: "Mix of static price and onchain price", + staticPrices: map[ocr2types.Account]big.Int{EthAcc: *EthPrice}, + inputTokens: []ocr2types.Account{EthAcc, OpAcc, ArbAcc}, + mockPrices: map[ocr2types.Account]*big.Int{ArbAcc: ArbPrice, OpAcc: OpPrice}, + want: []*big.Int{EthPrice, OpPrice, ArbPrice}, + }, + { + name: "Missing price should error", + staticPrices: map[ocr2types.Account]big.Int{}, + inputTokens: []ocr2types.Account{ArbAcc, OpAcc, EthAcc}, + mockPrices: map[ocr2types.Account]*big.Int{OpAcc: OpPrice, ArbAcc: ArbPrice}, + errorAccounts: []ocr2types.Account{EthAcc}, + want: nil, + wantErr: true, + }, + } + + for _, tc := range testCases { + contractReader := createMockReader(tc.mockPrices, tc.errorAccounts) + tokenPricesReader := OnchainTokenPricesReader{ + TokenPriceConfig: TokenPriceConfig{StaticPrices: tc.staticPrices}, + ContractReader: contractReader, + } + t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + result, err := tokenPricesReader.GetTokenPricesUSD(ctx, tc.inputTokens) + + if tc.wantErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, tc.want, result) + }) + } + +} + +func createMockReader(mockPrices map[ocr2types.Account]*big.Int, errorAccounts []ocr2types.Account) *mocks.ContractReaderMock { + reader := mocks.NewContractReaderMock() + for _, acc := range errorAccounts { + acc := acc + reader.On("GetLatestValue", mock.Anything, "PriceAggregator", "getTokenPrice", acc, mock.Anything).Return(fmt.Errorf("error")) + } + for acc, price := range mockPrices { + acc := acc + price := price + reader.On("GetLatestValue", mock.Anything, "PriceAggregator", "getTokenPrice", acc, mock.Anything).Run( + func(args mock.Arguments) { + arg := args.Get(4).(*big.Int) + arg.Set(price) + }).Return(nil) + } + return reader +} From 62b7b607a3cbf38c9616923a74222fcb833bf7d4 Mon Sep 17 00:00:00 2001 From: Will Winder Date: Thu, 20 Jun 2024 10:41:57 -0400 Subject: [PATCH 2/8] Fix error handling from USDC rate limiting call. (#1036) Fix bug where USDC rate limiter was checking the wrong error response. --- core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go | 6 +++--- .../services/ocr2/plugins/ccip/tokendata/usdc/usdc_test.go | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go index db0a2bd249..e7aac86033 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go +++ b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc.go @@ -164,7 +164,7 @@ func NewUSDCTokenDataReaderWithHttpClient( // attestation response. When called back to back, or multiple times // concurrently, responses are delayed according how the request interval is // configured. -func (s *TokenDataReader) ReadTokenData(ctx context.Context, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta, tokenIndex int) (messageAndAttestation []byte, err error) { +func (s *TokenDataReader) ReadTokenData(ctx context.Context, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta, tokenIndex int) ([]byte, error) { if tokenIndex < 0 || tokenIndex >= len(msg.TokenAmounts) { return nil, fmt.Errorf("token index out of bounds") } @@ -177,7 +177,7 @@ func (s *TokenDataReader) ReadTokenData(ctx context.Context, msg cciptypes.EVM2E if s.rate != nil { // Wait blocks until it the attestation API can be called or the // context is Done. - if waitErr := s.rate.Wait(ctx); err != nil { + if waitErr := s.rate.Wait(ctx); waitErr != nil { return nil, fmt.Errorf("usdc rate limiting error: %w", waitErr) } } @@ -197,7 +197,7 @@ func (s *TokenDataReader) ReadTokenData(ctx context.Context, msg cciptypes.EVM2E switch attestationResp.Status { case attestationStatusSuccess: // The USDC pool needs a combination of the message body and the attestation - messageAndAttestation, err = encodeMessageAndAttestation(messageBody, attestationResp.Attestation) + messageAndAttestation, err := encodeMessageAndAttestation(messageBody, attestationResp.Attestation) if err != nil { return nil, fmt.Errorf("failed to encode messageAndAttestation : %w", err) } diff --git a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc_test.go b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc_test.go index 1247f8dd20..c4221b2dc0 100644 --- a/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc_test.go +++ b/core/services/ocr2/plugins/ccip/tokendata/usdc/usdc_test.go @@ -335,7 +335,7 @@ func TestUSDCReader_rateLimiting(t *testing.T) { rateConfig: 100 * time.Millisecond, testDuration: 1 * time.Millisecond, timeout: 1 * time.Millisecond, - err: "usdc rate limiting error: rate: Wait(n=1) would exceed context deadline", + err: "usdc rate limiting error:", }, { name: "timeout after second request", @@ -343,7 +343,7 @@ func TestUSDCReader_rateLimiting(t *testing.T) { rateConfig: 100 * time.Millisecond, testDuration: 100 * time.Millisecond, timeout: 150 * time.Millisecond, - err: "usdc rate limiting error: rate: Wait(n=1) would exceed context deadline", + err: "usdc rate limiting error:", }, } @@ -405,7 +405,7 @@ func TestUSDCReader_rateLimiting(t *testing.T) { // Collect errors errorFound := false for err := range errorChan { - if tc.err != "" && !strings.Contains(err.Error(), tc.err) { + if tc.err != "" && strings.Contains(err.Error(), tc.err) { errorFound = true } else if err != nil && !strings.Contains(err.Error(), "get usdc token 0 end offset") { // Ignore that one error, it's expected because of how mocking is used. @@ -413,6 +413,7 @@ func TestUSDCReader_rateLimiting(t *testing.T) { require.Fail(t, "unexpected error", err) } } + if tc.err != "" { assert.True(t, errorFound) } From 99458582e694c0631dc6e8fbf32589774341cd27 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Thu, 20 Jun 2024 13:38:00 -0400 Subject: [PATCH 3/8] Fixes Borked Version Migration Test (#1062) CCIP public image is different --- .github/workflows/integration-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 00a83e9a60..733234f036 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -721,7 +721,7 @@ jobs: SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} CHAINLINK_ENV_USER: ${{ github.actor }} - CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + CHAINLINK_IMAGE: public.ecr.aws/w0i8p0z9/chainlink-ccip UPGRADE_VERSION: ${{ inputs.evm-ref || github.sha }} UPGRADE_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink TEST_LOG_LEVEL: debug From 7aaa83087b58d1e22b5780dbd6c65a86c114e828 Mon Sep 17 00:00:00 2001 From: dimitris Date: Thu, 20 Jun 2024 20:00:40 +0200 Subject: [PATCH 4/8] Separate manual execution threshold from oracle message visibility threshold. (#770) Support offRamp's offchainConfig `msgVisibilityInterval`, this field defines after what time the offchain code should stop attempting a ccip msg. If a value is not set, e.g. for existing offRamps that are not configured, it fallsback to a hardcoded default of `8h`. Also updated the tokenData worker to not rely on `msgVisibilityInterval` or `permisionlessExecThreshold` and removed some unused methods. chainlink-common PR: https://github.com/smartcontractkit/chainlink-common/pull/504 --------- Co-authored-by: Rens Rooimans --- .changeset/tasty-pianos-attend.md | 5 ++ .../ocr2/plugins/ccip/ccipexec/factory.go | 10 +++- .../plugins/ccip/ccipexec/initializers.go | 22 ++++---- .../ccip/internal/cache/commit_roots.go | 54 +++++++++---------- .../ccip/internal/cache/commit_roots_test.go | 2 +- .../ccip/internal/ccipdata/v1_0_0/offramp.go | 8 +-- .../internal/ccipdata/v1_0_0/offramp_test.go | 10 +++- .../ccip/internal/ccipdata/v1_2_0/offramp.go | 7 ++- .../ccip/internal/ccipdata/v1_5_0/offramp.go | 2 +- 9 files changed, 71 insertions(+), 49 deletions(-) create mode 100644 .changeset/tasty-pianos-attend.md diff --git a/.changeset/tasty-pianos-attend.md b/.changeset/tasty-pianos-attend.md new file mode 100644 index 0000000000..524cfea3c4 --- /dev/null +++ b/.changeset/tasty-pianos-attend.md @@ -0,0 +1,5 @@ +--- +"ccip": patch +--- + +add offchainConfig value to know after what time the offchain code should stop attempting a tx diff --git a/core/services/ocr2/plugins/ccip/ccipexec/factory.go b/core/services/ocr2/plugins/ccip/ccipexec/factory.go index db5eb9a266..1a18793a83 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/factory.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/factory.go @@ -111,6 +111,13 @@ func (rf *ExecutionReportingPluginFactory) NewReportingPluginFn(config types.Rep return reportingPluginAndInfo{}, fmt.Errorf("get onchain config from offramp: %w", err) } + msgVisibilityInterval := offchainConfig.MessageVisibilityInterval.Duration() + if msgVisibilityInterval.Seconds() == 0 { + rf.config.lggr.Info("MessageVisibilityInterval not set, falling back to PermissionLessExecutionThreshold") + msgVisibilityInterval = onchainConfig.PermissionLessExecutionThresholdSeconds + } + rf.config.lggr.Infof("MessageVisibilityInterval set to: %s", msgVisibilityInterval) + lggr := rf.config.lggr.Named("ExecutionReportingPlugin") plugin := &ExecutionReportingPlugin{ F: config.F, @@ -129,10 +136,11 @@ func (rf *ExecutionReportingPluginFactory) NewReportingPluginFn(config types.Rep offRampReader: rf.config.offRampReader, tokenPoolBatchedReader: rf.config.tokenPoolBatchedReader, inflightReports: newInflightExecReportsContainer(offchainConfig.InflightCacheExpiry.Duration()), - commitRootsCache: cache.NewCommitRootsCache(lggr, onchainConfig.PermissionLessExecutionThresholdSeconds, offchainConfig.RootSnoozeTime.Duration()), + commitRootsCache: cache.NewCommitRootsCache(lggr, msgVisibilityInterval, offchainConfig.RootSnoozeTime.Duration()), metricsCollector: rf.config.metricsCollector, chainHealthcheck: rf.config.chainHealthcheck, } + pluginInfo := types.ReportingPluginInfo{ Name: "CCIPExecution", // Setting this to false saves on calldata since OffRamp doesn't require agreement between NOPs diff --git a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go index b3b4fe2d41..e27816a8b2 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go @@ -45,7 +45,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/promwrapper" ) -const numTokenDataWorkers = 5 +var ( + // tokenDataWorkerTimeout defines 1) The timeout while waiting for a bg call to the token data 3P provider. + // 2) When a client requests token data and does not specify a timeout this value is used as a default. + // 5 seconds is a reasonable value for a timeout. + // At this moment, minimum OCR Delta Round is set to 30s and deltaGrace to 5s. Based on this configuration + // 5s for token data worker timeout is a reasonable default. + tokenDataWorkerTimeout = 5 * time.Second + // tokenDataWorkerNumWorkers is the number of workers that will be processing token data in parallel. + tokenDataWorkerNumWorkers = 5 +) var defaultNewReportingPluginRetryConfig = ccipdata.RetryConfig{InitialDelay: time.Second, MaxDelay: 5 * time.Minute} @@ -282,16 +291,11 @@ func jobSpecToExecPluginConfig(ctx context.Context, lggr logger.Logger, jb job.J params.offRampConfig.OnRamp, ) - onchainConfig, err := offRampReader.OnchainConfig(ctx) - if err != nil { - return nil, nil, nil, nil, fmt.Errorf("get onchain config from offramp reader: %w", err) - } - tokenBackgroundWorker := tokendata.NewBackgroundWorker( tokenDataProviders, - numTokenDataWorkers, - 5*time.Second, - onchainConfig.PermissionLessExecutionThresholdSeconds, + tokenDataWorkerNumWorkers, + tokenDataWorkerTimeout, + 2*tokenDataWorkerTimeout, ) return &ExecutionPluginStaticConfig{ lggr: execLggr, diff --git a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go index 9c859dc5f6..6f850ad39c 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots.go @@ -12,7 +12,7 @@ import ( ) const ( - // EvictionGracePeriod defines how long after the permissionless execution threshold a root is still kept in the cache + // EvictionGracePeriod defines how long after the messageVisibilityInterval a root is still kept in the cache EvictionGracePeriod = 1 * time.Hour // CleanupInterval defines how often roots cache is scanned to evict stale roots CleanupInterval = 30 * time.Minute @@ -25,7 +25,7 @@ type CommitsRootsCache interface { Snooze(merkleRoot [32]byte) // OldestRootTimestamp returns the oldest root timestamp that is not executed yet (minus 1 second). - // If there are no roots in the queue, it returns the permissionlessExecThreshold + // If there are no roots in the queue, it returns the messageVisibilityInterval OldestRootTimestamp() time.Time // AppendUnexecutedRoot appends the root to the unexecuted roots queue to keep track of the roots that are not executed yet // Roots has to be added in the order they are fetched from the database @@ -40,15 +40,15 @@ type commitRootsCache struct { // snoozedRoots is used to keep track of the roots that are temporary snoozed snoozedRoots *cache.Cache // unexecutedRootsQueue is used to keep track of the unexecuted roots in the order they are fetched from database (should be ordered by block_number, log_index) - // First run of Exec will fill the queue with all the roots that are not executed yet within the [now-permissionlessExecThreshold, now] window. - // When a root is executed, it is removed from the queue. Next database query instead of using entire permissionlessExecThrehsold window + // First run of Exec will fill the queue with all the roots that are not executed yet within the [now-messageVisibilityInterval, now] window. + // When a root is executed, it is removed from the queue. Next database query instead of using entire messageVisibilityInterval window // will use oldestRootTimestamp as the lower bound filter for block_timestamp. // This way we can reduce the number of database rows fetched with every OCR round. // We do it this way because roots for most of the cases are executed sequentially. // Instead of skipping snoozed roots after we fetch them from the database, we do that on the db level by narrowing the search window. // // Example - // permissionLessExecThresholds - 10 days, now - 2010-10-15 + // messageVisibilityInterval - 10 days, now - 2010-10-15 // We fetch all the roots that within the [2010-10-05, 2010-10-15] window and load them to the queue // [0xA - 2010-10-10, 0xB - 2010-10-11, 0xC - 2010-10-12] -> 0xA is the oldest root // We executed 0xA and a couple of rounds later, we mark 0xA as executed and snoozed that forever which removes it from the queue. @@ -60,40 +60,40 @@ type commitRootsCache struct { oldestRootTimestamp time.Time rootsQueueMu sync.RWMutex - // Both rootSnoozedTime and permissionLessExecutionThresholdDuration can be kept in the commitRootsCache without need to be updated. + // Both rootSnoozedTime and messageVisibilityInterval can be kept in the commitRootsCache without need to be updated. // Those config properties are populates via onchain/offchain config. When changed, OCR plugin will be restarted and cache initialized with new config. - rootSnoozedTime time.Duration - permissionLessExecutionThresholdDuration time.Duration + rootSnoozedTime time.Duration + messageVisibilityInterval time.Duration } func newCommitRootsCache( lggr logger.Logger, - permissionLessExecutionThresholdDuration time.Duration, + messageVisibilityInterval time.Duration, rootSnoozeTime time.Duration, evictionGracePeriod time.Duration, cleanupInterval time.Duration, ) *commitRootsCache { - executedRoots := cache.New(permissionLessExecutionThresholdDuration+evictionGracePeriod, cleanupInterval) + executedRoots := cache.New(messageVisibilityInterval+evictionGracePeriod, cleanupInterval) snoozedRoots := cache.New(rootSnoozeTime, cleanupInterval) return &commitRootsCache{ - lggr: lggr, - executedRoots: executedRoots, - snoozedRoots: snoozedRoots, - unexecutedRootsQueue: orderedmap.New[string, time.Time](), - rootSnoozedTime: rootSnoozeTime, - permissionLessExecutionThresholdDuration: permissionLessExecutionThresholdDuration, + lggr: lggr, + executedRoots: executedRoots, + snoozedRoots: snoozedRoots, + unexecutedRootsQueue: orderedmap.New[string, time.Time](), + rootSnoozedTime: rootSnoozeTime, + messageVisibilityInterval: messageVisibilityInterval, } } func NewCommitRootsCache( lggr logger.Logger, - permissionLessExecutionThresholdDuration time.Duration, + messageVisibilityInterval time.Duration, rootSnoozeTime time.Duration, ) *commitRootsCache { return newCommitRootsCache( lggr, - permissionLessExecutionThresholdDuration, + messageVisibilityInterval, rootSnoozeTime, EvictionGracePeriod, CleanupInterval, @@ -131,8 +131,8 @@ func (s *commitRootsCache) Snooze(merkleRoot [32]byte) { } func (s *commitRootsCache) OldestRootTimestamp() time.Time { - permissionlessExecWindow := time.Now().Add(-s.permissionLessExecutionThresholdDuration) - timestamp, ok := s.pickOldestRootBlockTimestamp(permissionlessExecWindow) + messageVisibilityInterval := time.Now().Add(-s.messageVisibilityInterval) + timestamp, ok := s.pickOldestRootBlockTimestamp(messageVisibilityInterval) if ok { return timestamp @@ -141,22 +141,22 @@ func (s *commitRootsCache) OldestRootTimestamp() time.Time { s.rootsQueueMu.Lock() defer s.rootsQueueMu.Unlock() - // If rootsSearchFilter is before permissionlessExecWindow, it means that we have roots that are stuck forever and will never be executed - // In that case, we wipe out the entire queue. Next round should start from the permissionlessExecThreshold and rebuild cache from scratch. + // If rootsSearchFilter is before messageVisibilityInterval, it means that we have roots that are stuck forever and will never be executed + // In that case, we wipe out the entire queue. Next round should start from the messageVisibilityInterval and rebuild cache from scratch. s.unexecutedRootsQueue = orderedmap.New[string, time.Time]() - return permissionlessExecWindow + return messageVisibilityInterval } -func (s *commitRootsCache) pickOldestRootBlockTimestamp(permissionlessExecWindow time.Time) (time.Time, bool) { +func (s *commitRootsCache) pickOldestRootBlockTimestamp(messageVisibilityInterval time.Time) (time.Time, bool) { s.rootsQueueMu.RLock() defer s.rootsQueueMu.RUnlock() - // If there are no roots in the queue, we can return the permissionlessExecWindow + // If there are no roots in the queue, we can return the messageVisibilityInterval if s.oldestRootTimestamp.IsZero() { - return permissionlessExecWindow, true + return messageVisibilityInterval, true } - if s.oldestRootTimestamp.After(permissionlessExecWindow) { + if s.oldestRootTimestamp.After(messageVisibilityInterval) { // Query used for fetching roots from the database is exclusive (block_timestamp > :timestamp) // so we need to subtract 1 second from the head timestamp to make sure that this root is included in the results return s.oldestRootTimestamp.Add(-time.Second), true diff --git a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go index bcb81b3a18..9dd8c365aa 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go @@ -232,7 +232,7 @@ func Test_UnexecutedRootsStaleQueue(t *testing.T) { assert.Equal(t, t1.Add(-time.Second), commitTs) // Reducing permissionLessExecutionThreshold works as speeding the clock - c.permissionLessExecutionThresholdDuration = 1 * time.Hour + c.messageVisibilityInterval = 1 * time.Hour commitTs = c.OldestRootTimestamp() assert.True(t, commitTs.Before(time.Now().Add(-1*time.Hour))) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go index 11bb98d59e..6495fe2174 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go @@ -90,10 +90,6 @@ func (d ExecOnchainConfig) Validate() error { return nil } -func (d ExecOnchainConfig) PermissionLessExecutionThresholdDuration() time.Duration { - return time.Duration(d.PermissionLessExecutionThresholdSeconds) * time.Second -} - // ExecOffchainConfig is the configuration for nodes executing committed CCIP messages (v1.0–v1.2). // It comes from the OffchainConfig field of the corresponding OCR2 plugin configuration. // NOTE: do not change the JSON format of this struct without consulting with the RDD people first. @@ -112,6 +108,8 @@ type ExecOffchainConfig struct { InflightCacheExpiry config.Duration // See [ccipdata.ExecOffchainConfig.RootSnoozeTime] RootSnoozeTime config.Duration + // See [ccipdata.ExecOffchainConfig.MessageVisibilityInterval] + MessageVisibilityInterval config.Duration } func (c ExecOffchainConfig) Validate() error { @@ -416,12 +414,14 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o RelativeBoostPerWaitHour: offchainConfigParsed.RelativeBoostPerWaitHour, InflightCacheExpiry: offchainConfigParsed.InflightCacheExpiry, RootSnoozeTime: offchainConfigParsed.RootSnoozeTime, + MessageVisibilityInterval: offchainConfigParsed.MessageVisibilityInterval, } onchainConfig := cciptypes.ExecOnchainConfig{ PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), Router: cciptypes.Address(onchainConfigParsed.Router.String()), } gasPriceEstimator := prices.NewExecGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0) + o.UpdateDynamicConfig(onchainConfig, offchainConfig, gasPriceEstimator) o.Logger.Infow("Starting exec plugin", diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go index 8f3d0d6ca3..f1fb4ddcd7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_test.go @@ -36,6 +36,7 @@ func TestExecOffchainConfig100_Encoding(t *testing.T) { RelativeBoostPerWaitHour: 0.07, InflightCacheExpiry: *config.MustNewDuration(64 * time.Second), RootSnoozeTime: *config.MustNewDuration(128 * time.Minute), + MessageVisibilityInterval: *config.MustNewDuration(6 * time.Hour), }, }, { @@ -48,6 +49,7 @@ func TestExecOffchainConfig100_Encoding(t *testing.T) { RelativeBoostPerWaitHour: 0, InflightCacheExpiry: *config.MustNewDuration(0), RootSnoozeTime: *config.MustNewDuration(0), + MessageVisibilityInterval: *config.MustNewDuration(0), }, expectErr: true, }, @@ -83,7 +85,7 @@ func TestExecOffchainConfig100_Encoding(t *testing.T) { } func TestExecOffchainConfig100_AllFieldsRequired(t *testing.T) { - config := ExecOffchainConfig{ + cfg := ExecOffchainConfig{ SourceFinalityDepth: 3, DestOptimisticConfirmations: 6, DestFinalityDepth: 3, @@ -92,13 +94,17 @@ func TestExecOffchainConfig100_AllFieldsRequired(t *testing.T) { InflightCacheExpiry: *config.MustNewDuration(64 * time.Second), RootSnoozeTime: *config.MustNewDuration(128 * time.Minute), } - encoded, err := ccipconfig.EncodeOffchainConfig(&config) + encoded, err := ccipconfig.EncodeOffchainConfig(&cfg) require.NoError(t, err) var configAsMap map[string]any err = json.Unmarshal(encoded, &configAsMap) require.NoError(t, err) for keyToDelete := range configAsMap { + if keyToDelete == "MessageVisibilityInterval" { + continue // this field is optional + } + partialConfig := make(map[string]any) for k, v := range configAsMap { if k != keyToDelete { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go index c5b7968296..94c9a45e26 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go @@ -72,10 +72,6 @@ func (d ExecOnchainConfig) Validate() error { return nil } -func (d ExecOnchainConfig) PermissionLessExecutionThresholdDuration() time.Duration { - return time.Duration(d.PermissionLessExecutionThresholdSeconds) * time.Second -} - // JSONExecOffchainConfig is the configuration for nodes executing committed CCIP messages (v1.2). // It comes from the OffchainConfig field of the corresponding OCR2 plugin configuration. // NOTE: do not change the JSON format of this struct without consulting with the RDD people first. @@ -98,6 +94,8 @@ type JSONExecOffchainConfig struct { InflightCacheExpiry config.Duration // See [ccipdata.ExecOffchainConfig.RootSnoozeTime] RootSnoozeTime config.Duration + // See [ccipdata.ExecOffchainConfig.MessageVisibilityInterval] + MessageVisibilityInterval config.Duration } func (c JSONExecOffchainConfig) Validate() error { @@ -173,6 +171,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o RelativeBoostPerWaitHour: offchainConfigParsed.RelativeBoostPerWaitHour, InflightCacheExpiry: offchainConfigParsed.InflightCacheExpiry, RootSnoozeTime: offchainConfigParsed.RootSnoozeTime, + MessageVisibilityInterval: offchainConfigParsed.MessageVisibilityInterval, } onchainConfig := cciptypes.ExecOnchainConfig{ PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go index 9aed6b6dde..89d3047381 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -157,6 +156,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o RelativeBoostPerWaitHour: offchainConfigParsed.RelativeBoostPerWaitHour, InflightCacheExpiry: offchainConfigParsed.InflightCacheExpiry, RootSnoozeTime: offchainConfigParsed.RootSnoozeTime, + MessageVisibilityInterval: offchainConfigParsed.MessageVisibilityInterval, } onchainConfig := cciptypes.ExecOnchainConfig{ PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), From f24af7895275f9edb5068c130cd42e8de05ef039 Mon Sep 17 00:00:00 2001 From: Amir Y <83904651+amirylm@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:45:43 +0300 Subject: [PATCH 5/8] Log chain ids in addition to chain selectors (#1063) ## Motivation ## Solution --- .changeset/early-readers-work.md | 6 ++++++ .../plugins/liquiditymanager/discoverer/evm.go | 15 ++++++++------- .../ocr2/plugins/liquiditymanager/graph/graph.go | 15 ++++++++++++++- .../plugins/liquiditymanager/models/models.go | 5 +++++ .../ocr2/plugins/liquiditymanager/plugin.go | 13 +++++++------ .../plugins/liquiditymanager/plugin_validate.go | 4 ++-- 6 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 .changeset/early-readers-work.md diff --git a/.changeset/early-readers-work.md b/.changeset/early-readers-work.md new file mode 100644 index 0000000000..6da59d5883 --- /dev/null +++ b/.changeset/early-readers-work.md @@ -0,0 +1,6 @@ +--- +"ccip": patch +--- + +New function on NetworkSelector to get ChainID #added +Align logs and include chainID #changed diff --git a/core/services/ocr2/plugins/liquiditymanager/discoverer/evm.go b/core/services/ocr2/plugins/liquiditymanager/discoverer/evm.go index 8b2a48bb9e..4cc3377705 100644 --- a/core/services/ocr2/plugins/liquiditymanager/discoverer/evm.go +++ b/core/services/ocr2/plugins/liquiditymanager/discoverer/evm.go @@ -47,11 +47,12 @@ func (e *evmDiscoverer) Discover(ctx context.Context) (graph.Graph, error) { NetworkSelector: e.masterSelector, LiquidityManager: e.masterLiquidityManager, }, func(ctx context.Context, v graph.Vertex) (graph.Data, []graph.Vertex, error) { + lggr := e.lggr.With("selector", v.NetworkSelector, "chainID", v.NetworkSelector.ChainID(), "addr", v.LiquidityManager) d, n, err := e.getVertexData(ctx, v) if err != nil { - e.lggr.Warnw("failed to get vertex data", "selector", v.NetworkSelector, "addr", v.LiquidityManager, "error", err) + lggr.Warnw("failed to get vertex data", "error", err) } else { - e.lggr.Debugw("Got vertex data", "selector", v.NetworkSelector, "addr", v.LiquidityManager, "data", d) + lggr.Debugw("Got vertex data", "data", d) } return d, n, err }) @@ -165,13 +166,13 @@ func (e *evmDiscoverer) getVertexData(ctx context.Context, v graph.Vertex) (grap func (e *evmDiscoverer) updateLiquidity(ctx context.Context, selector models.NetworkSelector, g graph.Graph, liquidityGetter evmLiquidityGetter) error { lmAddress, err := g.GetLiquidityManagerAddress(selector) if err != nil { - return fmt.Errorf("get rebalancer address: %w", err) + return fmt.Errorf("get rebalancer address(%d, %s): %w", selector, lmAddress, err) } liquidity, err := liquidityGetter(ctx, selector, common.Address(lmAddress)) if err != nil { - return fmt.Errorf("get liquidity: %w", err) + return fmt.Errorf("get liquidity (%d, %s): %w", selector, lmAddress, err) } - e.lggr.Debugw("Updating liquidity", "liquidity", liquidity, "selector", selector, "lmAddress", lmAddress) + e.lggr.Debugw("Updating liquidity", "liquidity", liquidity, "selector", selector, "chainID", selector.ChainID(), "lmAddress", lmAddress) _ = g.SetLiquidity(selector, liquidity) // TODO: handle non-existing network return nil } @@ -190,11 +191,11 @@ func (e *evmDiscoverer) getDep(selector models.NetworkSelector) (*evmDep, bool) func (e *evmDiscoverer) defaultLiquidityGetter(ctx context.Context, selector models.NetworkSelector, lmAddress common.Address) (*big.Int, error) { dep, ok := e.getDep(selector) if !ok { - return nil, fmt.Errorf("no client for master chain %+v", selector) + return nil, fmt.Errorf("no client for master chain %d", selector) } rebal, err := liquiditymanager.NewLiquidityManager(lmAddress, dep.ethClient) if err != nil { - return nil, fmt.Errorf("new liquiditymanager: %w", err) + return nil, fmt.Errorf("new liquiditymanager (%d, %s): %w", selector, lmAddress, err) } return rebal.GetLiquidity(&bind.CallOpts{ Context: ctx, diff --git a/core/services/ocr2/plugins/liquiditymanager/graph/graph.go b/core/services/ocr2/plugins/liquiditymanager/graph/graph.go index 6d15afa566..625c8ac81e 100644 --- a/core/services/ocr2/plugins/liquiditymanager/graph/graph.go +++ b/core/services/ocr2/plugins/liquiditymanager/graph/graph.go @@ -136,7 +136,20 @@ func (g *liquidityGraph) String() string { g.lock.RLock() defer g.lock.RUnlock() - return fmt.Sprintf("Graph{networksGraph: %+v, networkBalance: %+v}", g.adj, g.data) + type network struct { + Selector models.NetworkSelector + ChainID uint64 + } + adj := make([]network, 0, len(g.adj)) + for n := range g.adj { + adj = append(adj, network{Selector: n, ChainID: n.ChainID()}) + } + data := make(map[network]Data, len(g.data)) + for n, d := range g.data { + data[network{Selector: n, ChainID: n.ChainID()}] = d + } + + return fmt.Sprintf("Graph{graph: %+v, data: %+v}", adj, data) } func (g *liquidityGraph) Reset() { diff --git a/core/services/ocr2/plugins/liquiditymanager/models/models.go b/core/services/ocr2/plugins/liquiditymanager/models/models.go index 4c116de964..e9880590fe 100644 --- a/core/services/ocr2/plugins/liquiditymanager/models/models.go +++ b/core/services/ocr2/plugins/liquiditymanager/models/models.go @@ -52,6 +52,11 @@ func (n NetworkSelector) Type() NetworkType { return NetworkTypeUnknown } +func (n NetworkSelector) ChainID() uint64 { + chainID, _ := chainsel.ChainIdFromSelector(uint64(n)) + return chainID +} + type NetworkType string // ProposedTransfer is a transfer that is proposed by the rebalancing algorithm. diff --git a/core/services/ocr2/plugins/liquiditymanager/plugin.go b/core/services/ocr2/plugins/liquiditymanager/plugin.go index 9b89bc7c7e..23a6f21136 100644 --- a/core/services/ocr2/plugins/liquiditymanager/plugin.go +++ b/core/services/ocr2/plugins/liquiditymanager/plugin.go @@ -439,7 +439,8 @@ func (p *Plugin) Close() error { var errs []error for _, networkID := range p.liquidityGraph.GetNetworks() { - p.lggr.Infow("closing liquidityManager network", "network", networkID) + lggr := p.lggr.With("network", networkID, "chainID", networkID.ChainID()) + lggr.Infow("closing liquidityManager network") liquidityManagerAddress, err := p.liquidityGraph.GetLiquidityManagerAddress(networkID) if err != nil { @@ -458,7 +459,7 @@ func (p *Plugin) Close() error { continue } - p.lggr.Infow("finished closing liquidityManager network", "network", networkID, "liquidityManager", liquidityManagerAddress.String()) + lggr.Infow("finished closing liquidityManager network", "liquidityManager", liquidityManagerAddress.String()) } return multierr.Combine(errs...) @@ -497,7 +498,7 @@ func (p *Plugin) syncGraph(ctx context.Context) error { } func (p *Plugin) loadPendingTransfers(ctx context.Context, lggr logger.Logger) ([]models.PendingTransfer, error) { - p.lggr.Infow("loading pending transfers") + lggr.Infow("loading pending transfers") pendingTransfers := make([]models.PendingTransfer, 0) edges, err := p.liquidityGraph.GetEdges() @@ -505,13 +506,14 @@ func (p *Plugin) loadPendingTransfers(ctx context.Context, lggr logger.Logger) ( return nil, fmt.Errorf("get edges: %w", err) } for _, edge := range edges { + logger := lggr.With("sourceNetwork", edge.Source, "sourceChainID", edge.Source.ChainID(), "destNetwork", edge.Dest, "destChainID", edge.Dest.ChainID()) bridge, err := p.bridgeFactory.NewBridge(edge.Source, edge.Dest) if err != nil { return nil, fmt.Errorf("init bridge: %w", err) } if bridge == nil { - lggr.Warnw("no bridge found for network pair", "sourceNetwork", edge.Source, "destNetwork", edge.Dest) + logger.Warn("no bridge found for network pair") continue } @@ -529,11 +531,10 @@ func (p *Plugin) loadPendingTransfers(ctx context.Context, lggr logger.Logger) ( return nil, fmt.Errorf("get pending transfers: %w", err) } - lggr.Infow("loaded pending transfers for network", "network", edge.Source, "pendingTransfers", netPendingTransfers) + logger.Infow("loaded pending transfers for network", "pendingTransfers", netPendingTransfers) pendingTransfers = append(pendingTransfers, netPendingTransfers...) } - // todo: why do we add this here? it's not used anywhere return pendingTransfers, nil } diff --git a/core/services/ocr2/plugins/liquiditymanager/plugin_validate.go b/core/services/ocr2/plugins/liquiditymanager/plugin_validate.go index 1774772066..491b885065 100644 --- a/core/services/ocr2/plugins/liquiditymanager/plugin_validate.go +++ b/core/services/ocr2/plugins/liquiditymanager/plugin_validate.go @@ -93,11 +93,11 @@ func validateItems[T any](keyFn func(T) string, items []T, validateFns ...func(T for _, item := range items { k := keyFn(item) if existing[k] { - return fmt.Errorf("duplicated item") + return fmt.Errorf("duplicated item (%s)", k) } for _, validateFn := range validateFns { if err := validateFn(item); err != nil { - return fmt.Errorf("invalid item: %w", err) + return fmt.Errorf("invalid item (%s): %w", k, err) } } existing[k] = true From 969d44ad32058d75e60630664e131167acc944e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evaldas=20Lato=C5=A1kinas?= <34982762+elatoskinas@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:33:53 +0200 Subject: [PATCH 6/8] MultiOffRamp - size optimizations (#991) ## Motivation Optimizes the contract size for the merged MultiOffRamp + CommitStore to be able to fit the deployment size limits ## Solution Currently the margin is at -0.972KB with 3600 optimizer runs. The contract size fits the space with 1800 optimizer runs. The contract size can further be reduced, and the optimizer runs increased after the Nonce Manager is integrated into the MultiOffRamp Each optimization is split into a separate commit. Complete list: * Remove in-depth message validations -> these will be moved off-chain (ticket already created) * Move `isCursed` to shared internal function * Move forked chain check, curse check and source config enabled check to common internal function * ~~Move source chain config + curse check to single shared function (used in both exec & commit)~~ * ~~Move zero address check to internal lib~~ * Remove global pausing from the multi-offramp -> there are 4 alternative methods of achieving pausing: * Per-lane: using `IMessageValidator` (execution-only), disabling the source chain config, cursing the lane via RMN * Globally: implementing the global pause in the RMN * The savings are significant, at around ~0.8KB * Split StaticConfig and DynamicConfig set events * Get rid of `Any2EVMMessageRoute` and use 2 internal functions to solve stack depth (same as the OffRamp changes) * Other contract size golfing: variable caching, inlining * Compile with lower optimizer runs for the multi-offramp * **Update**: OCR3 no longer needs a `uniqueReports` distinction * **Other fix**: OCR3 now uses sequenceNumbers --- contracts/.changeset/gentle-spoons-vanish.md | 5 + contracts/gas-snapshots/ccip.gas-snapshot | 349 ++++---- .../scripts/native_solc_compile_all_ccip | 7 +- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 30 +- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 403 ++++----- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 4 +- .../helpers/EVM2EVMMultiOffRampHelper.sol | 29 +- .../v0.8/ccip/test/ocr/MultiOCR3Base.t.sol | 84 +- .../ccip/test/ocr/MultiOCR3BaseSetup.t.sol | 14 +- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 834 +++++++++--------- .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 25 +- .../evm_2_evm_multi_offramp.go | 490 +++------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 13 files changed, 983 insertions(+), 1293 deletions(-) create mode 100644 contracts/.changeset/gentle-spoons-vanish.md diff --git a/contracts/.changeset/gentle-spoons-vanish.md b/contracts/.changeset/gentle-spoons-vanish.md new file mode 100644 index 0000000000..38cfb5eff2 --- /dev/null +++ b/contracts/.changeset/gentle-spoons-vanish.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts-ccip': minor +--- + +#changed MultiOffRamp contract size optimizations diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index ed2660af39..4af4b21269 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -66,152 +66,148 @@ CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424253) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1106837) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 263045) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 93686) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12334) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() (gas: 87721) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 87454) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainPrevOffRamp_Revert() (gas: 87647) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 102154) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 12423) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 12398) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 278879) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 224306) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 149627) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 178945) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 136157) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 520361) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10441) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38297) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108537) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116989) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 262944) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 93628) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12398) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() (gas: 87827) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 87538) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainPrevOffRamp_Revert() (gas: 87686) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 102183) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 12487) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 12462) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 278563) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 223913) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 149702) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 178741) +EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 136083) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 520278) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10487) EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17112) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7043083) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6626006) -EVM2EVMMultiOffRamp_commit:test_SingleReport_Success() (gas: 161050) -EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 120903) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 7061858) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6711837) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 100030) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 98610) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 100063) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 96367) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 96457) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7092600) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6675266) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 156875) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 140719) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7454908) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20642) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 255841) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 22871) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 208246) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50914) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50402) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 221352) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 77140) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 288038) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 81184) -EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 37471) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21760) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidMessageId_Revert() (gas: 41784) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 448866) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 53535) -EVM2EVMMultiOffRamp_executeSingleReport:test_MessageTooLarge_Revert() (gas: 154093) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampAddress_Revert() (gas: 44609) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingSourceChainSelector_Revert() (gas: 41676) -EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 37730) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 170541) -EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 182146) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 49176) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 406064) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 233339) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 180915) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251955) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 119124) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 383701) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 55923) -EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 53355) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 528885) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 466412) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35849) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 518813) -EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 516211) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnsupportedNumberOfTokens_Revert() (gas: 65466) -EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 483429) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 147680) -EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 239585) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 239530) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 290102) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 270581) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247819) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 235794) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 7627747) -EVM2EVMMultiOffRamp_execute_upgrade:test_Upgraded_Success() (gas: 136510) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3590746) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 117760) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 86873) -EVM2EVMMultiOffRamp_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 75619) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79972) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 28721) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 152516) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 198036) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 28254) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 160615) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 495948) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2371462) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 200146) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 200742) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 642734) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 287749) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnOnRampAddress_Success() (gas: 11027) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnSourceChain_Success() (gas: 11080) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9191) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 171896) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 33312) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 70902) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 50988) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 80934) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 192892) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 289884) -EVM2EVMMultiOffRamp_reportCommit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 58215) -EVM2EVMMultiOffRamp_reportCommit:test_InvalidInterval_Revert() (gas: 51845) -EVM2EVMMultiOffRamp_reportCommit:test_InvalidRootRevert() (gas: 50945) -EVM2EVMMultiOffRamp_reportCommit:test_OnlyGasPriceUpdates_Success() (gas: 64713) -EVM2EVMMultiOffRamp_reportCommit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 68997) -EVM2EVMMultiOffRamp_reportCommit:test_OnlyTokenPriceUpdates_Success() (gas: 64689) -EVM2EVMMultiOffRamp_reportCommit:test_Paused_Revert() (gas: 40466) -EVM2EVMMultiOffRamp_reportCommit:test_ReportAndPriceUpdate_Success() (gas: 119841) -EVM2EVMMultiOffRamp_reportCommit:test_ReportOnlyRootSuccess_gas() (gas: 80225) -EVM2EVMMultiOffRamp_reportCommit:test_RootAlreadyCommitted_Revert() (gas: 90494) -EVM2EVMMultiOffRamp_reportCommit:test_SourceChainNotEnabled_Revert() (gas: 51221) -EVM2EVMMultiOffRamp_reportCommit:test_StaleReportWithRoot_Success() (gas: 142995) -EVM2EVMMultiOffRamp_reportCommit:test_Unhealthy_Revert() (gas: 69784) -EVM2EVMMultiOffRamp_reportCommit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 140904) -EVM2EVMMultiOffRamp_reportCommit:test_ZeroEpochAndRound_Revert() (gas: 17735) -EVM2EVMMultiOffRamp_reportExec:test_IncorrectArrayType_Revert() (gas: 10004) -EVM2EVMMultiOffRamp_reportExec:test_LargeBatch_Success() (gas: 1471370) -EVM2EVMMultiOffRamp_reportExec:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 293483) -EVM2EVMMultiOffRamp_reportExec:test_MultipleReports_Success() (gas: 224678) -EVM2EVMMultiOffRamp_reportExec:test_NonArray_Revert() (gas: 22774) -EVM2EVMMultiOffRamp_reportExec:test_SingleReport_Success() (gas: 133819) -EVM2EVMMultiOffRamp_reportExec:test_ZeroReports_Revert() (gas: 9899) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11377) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 155750) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14765) -EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 12314) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14413) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 45435) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 40479) -EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11043) -EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound:test_PriceEpochCleared_Success() (gas: 242916) -EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20502) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 243932) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 252523) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 306347) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 285955) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 120913) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 123006) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 83460) -EVM2EVMMultiOffRamp_verify:test_Paused_Revert() (gas: 19039) -EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 53617) +EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 66098) +EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59748) +EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58828) +EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6589672) +EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 6172841) +EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 108294) +EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 118230) +EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 108270) +EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 160084) +EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 135123) +EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136820) +EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59096) +EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225356) +EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 119693) +EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77594) +EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 207937) +EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6584042) +EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47717) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 6242606) +EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 101021) +EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 97965) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 101074) +EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 95722) +EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 95789) +EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17299) +EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1490148) +EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 330182) +EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 247239) +EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6640018) +EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6222985) +EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 30044) +EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 156627) +EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 140575) +EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7002111) +EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17174) +EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20709) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 255851) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 22860) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 208240) +EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50948) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50458) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 235451) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 91273) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 288058) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 95383) +EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 37472) +EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 24087) +EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidMessageId_Revert() (gas: 41948) +EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 448634) +EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 53653) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampAddress_Revert() (gas: 44740) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingSourceChainSelector_Revert() (gas: 41840) +EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 37658) +EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 170378) +EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 182190) +EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 47177) +EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 405951) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 233102) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 180689) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251836) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 119083) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 383789) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 56096) +EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 51403) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 528700) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 466304) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 38177) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 518752) +EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 516084) +EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 483321) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 147823) +EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 239478) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 239370) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 289847) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 270573) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247753) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 235728) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 7174963) +EVM2EVMMultiOffRamp_execute_upgrade:test_Upgraded_Success() (gas: 136472) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3652910) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118102) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87240) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 80029) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 28684) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 152312) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 199879) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 28213) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 160718) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 497791) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2371474) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 201989) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 202563) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 651271) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 287191) +EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnOnRampAddress_Success() (gas: 10983) +EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnSourceChain_Success() (gas: 11029) +EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9135) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165404) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 26964) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63569) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44686) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 80707) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 185601) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 284048) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11420) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 211875) +EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14223) +EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11729) +EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 13885) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55566) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33576) +EVM2EVMMultiOffRamp_setLatestPriceSequenceNumber:test_OnlyOwner_Revert() (gas: 11033) +EVM2EVMMultiOffRamp_setLatestPriceSequenceNumber:test_PriceEpochCleared_Success() (gas: 242133) +EVM2EVMMultiOffRamp_setLatestPriceSequenceNumber:test_setLatestPriceSequenceNumber_Success() (gas: 20534) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 243929) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 252586) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 306761) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 286008) +EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176393) +EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178464) +EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 138858) +EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51501) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 33520) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16645) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 30418) @@ -574,38 +570,37 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsA MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28509) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17430) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17485) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59396) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44544) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283912) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 423049) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 512762) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 830661) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 458492) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12332) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2146686) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141953) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 817933) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171416) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30500) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254663) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 862620) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 476906) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 43809) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 49355) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 81495) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 67118) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33474) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 85456) -MultiOCR3Base_transmit:test_TransmitSignersNonUniqueReports_gas_Success() (gas: 34208) -MultiOCR3Base_transmit:test_TransmitUniqueReportSigners_gas_Success() (gas: 53798) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47174) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25720) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18768) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24205) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 62379) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39969) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33006) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1339048) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422848) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511694) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 829593) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457446) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2143220) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141744) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 808478) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171331) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30298) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254454) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861521) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475825) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42837) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48442) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76930) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 66127) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33419) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79521) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 34131) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47114) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25682) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18726) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1395580) OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12171) OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42233) OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84124) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 31c4bfff6d..2c209d69d6 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -10,6 +10,7 @@ SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=26000 OPTIMIZE_RUNS_OFFRAMP=18000 OPTIMIZE_RUNS_ONRAMP=3600 +OPTIMIZE_RUNS_MULTI_OFFRAMP=1800 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" @@ -27,10 +28,14 @@ compileContract () { local optimize_runs=$OPTIMIZE_RUNS case $1 in - "ccip/offRamp/EVM2EVMOffRamp.sol" | "ccip/offRamp/EVM2EVMMultiOffRamp.sol") + "ccip/offRamp/EVM2EVMOffRamp.sol") echo "OffRamp uses $OPTIMIZE_RUNS_OFFRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_OFFRAMP ;; + "ccip/offRamp/EVM2EVMMultiOffRamp.sol") + echo "MultiOffRamp uses $OPTIMIZE_RUNS_MULTI_OFFRAMP optimizer runs." + optimize_runs=$OPTIMIZE_RUNS_MULTI_OFFRAMP + ;; "ccip/onRamp/EVM2EVMMultiOnRamp.sol" | "ccip/onRamp/EVM2EVMOnRamp.sol") echo "OnRamp uses $OPTIMIZE_RUNS_ONRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_ONRAMP diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index e5a474241b..1872ae276c 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -// TODO: consider splitting configs & verification logic off to auth library (if size is prohibitive) /// @notice Onchain verification of reports from the offchain reporting protocol /// with multiple OCR plugin support. abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { @@ -50,7 +49,6 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { bytes32 configDigest; uint8 F; // ──────────────────────────────╮ maximum number of faulty/dishonest oracles the system can tolerate uint8 n; // │ number of signers / transmitters - bool uniqueReports; // │ if true, the reports should be unique bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification } @@ -85,7 +83,6 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { bytes32 configDigest; // Config digest to update to uint8 ocrPluginType; // ──────────────────╮ OCR plugin type to update config for uint8 F; // │ maximum number of faulty/dishonest oracles - bool uniqueReports; // │ if true, the reports should be unique bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification address[] signers; // signing address of each oracle address[] transmitters; // transmission address of each oracle (i.e. the address the oracle actually sends transactions to the contract from) @@ -143,12 +140,8 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // If F is 0, then the config is not yet set if (configInfo.F == 0) { - configInfo.uniqueReports = ocrConfigArgs.uniqueReports; configInfo.isSignatureVerificationEnabled = ocrConfigArgs.isSignatureVerificationEnabled; - } else if ( - configInfo.uniqueReports != ocrConfigArgs.uniqueReports - || configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled - ) { + } else if (configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled) { revert StaticConfigCannotBeChanged(ocrPluginType); } @@ -228,15 +221,13 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly bytes32[3] calldata reportContext, bytes calldata report, - // TODO: revisit trade-off - converting this to calldata and using one CONSTANT_LENGTH_COMPONENT - // decreases contract size by ~220B, decreasees commit gas usage by ~400 gas, but increases exec gas usage by ~3600 gas bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs // signatures ) internal { // reportContext consists of: // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[1]: 24 byte padding, 8 byte sequence number // reportContext[2]: ExtraHash ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; bytes32 configDigest = reportContext[0]; @@ -259,7 +250,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest // calculated from chain A and so OCR reports will be valid on both forks. - if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); + _whenChainNotForked(); // Scoping this reduces stack pressure and gas usage { @@ -278,13 +269,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { if (configInfo.isSignatureVerificationEnabled) { // Scoping to reduce stack pressure { - uint256 expectedNumSignatures; - if (configInfo.uniqueReports) { - expectedNumSignatures = (configInfo.n + configInfo.F) / 2 + 1; - } else { - expectedNumSignatures = configInfo.F + 1; - } - if (rs.length != expectedNumSignatures) revert WrongNumberOfSignatures(); + if (rs.length != configInfo.F + 1) revert WrongNumberOfSignatures(); if (rs.length != ss.length) revert SignaturesOutOfRegistration(); } @@ -292,7 +277,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { _verifySignatures(ocrPluginType, h, rs, ss, rawVs); } - emit Transmitted(ocrPluginType, configDigest, uint32(uint256(reportContext[1]) >> 8)); + emit Transmitted(ocrPluginType, configDigest, uint64(uint256(reportContext[1]))); } /// @notice verifies the signatures of a hashed report value for one OCR plugin type @@ -324,6 +309,11 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { } } + /// @notice Validates that the chain ID has not diverged after deployment. Reverts if the chain IDs do not match + function _whenChainNotForked() internal view { + if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); + } + /// @notice information about current offchain reporting protocol configuration /// @param ocrPluginType OCR plugin type to return config details for /// @return ocrConfig OCR config for the plugin type diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index c76a26e567..1b6ed6eb21 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -36,14 +36,11 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 error AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); error AlreadyExecuted(uint64 sourceChainSelector, uint64 sequenceNumber); - error ZeroAddressNotAllowed(); error ZeroChainSelectorNotAllowed(); error ExecutionError(bytes32 messageId, bytes error); error SourceChainNotEnabled(uint64 sourceChainSelector); - error MessageTooLarge(bytes32 messageId, uint256 maxSize, uint256 actualSize); error TokenDataMismatch(uint64 sourceChainSelector, uint64 sequenceNumber); error UnexpectedTokenData(); - error UnsupportedNumberOfTokens(uint64 sourceChainSelector, uint64 sequenceNumber); error ManualExecutionNotYetEnabled(uint64 sourceChainSelector); error ManualExecutionGasLimitMismatch(); error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, uint256 index, uint256 newLimit); @@ -62,10 +59,11 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 error InvalidStaticConfig(uint64 sourceChainSelector); error StaleCommitReport(); error InvalidInterval(uint64 sourceChainSelector, Interval interval); - error PausedError(); + error ZeroAddressNotAllowed(); /// @dev Atlas depends on this event, if changing, please notify Atlas. - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); + event StaticConfigSet(StaticConfig staticConfig); + event DynamicConfigSet(DynamicConfig dynamicConfig); event SkippedIncorrectNonce(uint64 sourceChainSelector, uint64 nonce, address sender); event SkippedSenderWithPreviousRampMessageInflight(uint64 sourceChainSelector, uint64 nonce, address sender); /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. @@ -79,12 +77,10 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 event SourceChainSelectorAdded(uint64 sourceChainSelector); event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig); event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); - event Paused(address account); - event Unpaused(address account); /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. event CommitReportAccepted(CommitReport report); event RootRemoved(bytes32 root); - event LatestPriceEpochAndRoundSet(uint40 oldEpochAndRound, uint40 newEpochAndRound); + event LatestPriceSequenceNumberSet(uint64 oldSequenceNumber, uint64 newSequenceNumber); /// @notice Static offRamp config /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. @@ -121,19 +117,10 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 uint32 permissionLessExecutionThresholdSeconds; // │ Waiting time before manual execution is enabled uint32 maxTokenTransferGas; // │ Maximum amount of gas passed on to token `transfer` call uint32 maxPoolReleaseOrMintGas; // ─────────────────╯ Maximum amount of gas passed on to token pool when calling releaseOrMint - uint16 maxNumberOfTokensPerMsg; // ──╮ Maximum number of ERC20 token transfers that can be included per message - uint32 maxDataBytes; // │ Maximum payload data size in bytes - address messageValidator; // ────────╯ Optional message validator to validate incoming messages (zero address = no validator) + address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) address priceRegistry; // Price registry address on the local chain } - /// @notice Struct that represents a message route (sender -> receiver and source chain) - struct Any2EVMMessageRoute { - bytes sender; // Message sender - uint64 sourceChainSelector; // ───╮ Source chain that the message originates from - address receiver; // ─────────────╯ Address that receives the message - } - /// @notice a sequenceNumber interval /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct Interval { @@ -175,7 +162,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 /// @notice SourceConfig per chain /// (forms lane configurations from sourceChainSelector => StaticConfig.chainSelector) - mapping(uint64 sourceChainSelector => SourceChainConfig) internal s_sourceChainConfigs; + mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; // STATE /// @dev The expected nonce for a given sender per source chain. @@ -191,15 +178,14 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 // sourceChainSelector => merkleRoot => timestamp when received mapping(uint64 sourceChainSelector => mapping(bytes32 merkleRoot => uint256 timestamp)) internal s_roots; - /// @dev The epoch and round of the last report - uint40 private s_latestPriceEpochAndRound; - /// @dev Whether this OffRamp is paused or not - bool private s_paused = false; + /// @dev The sequence number of the last report + uint64 private s_latestPriceSequenceNumber; constructor(StaticConfig memory staticConfig, SourceChainConfigArgs[] memory sourceChainConfigs) MultiOCR3Base() { if (staticConfig.rmnProxy == address(0) || staticConfig.tokenAdminRegistry == address(0)) { revert ZeroAddressNotAllowed(); } + if (staticConfig.chainSelector == 0) { revert ZeroChainSelectorNotAllowed(); } @@ -207,6 +193,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 i_chainSelector = staticConfig.chainSelector; i_rmnProxy = staticConfig.rmnProxy; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; + emit StaticConfigSet(staticConfig); _applySourceChainConfigUpdates(sourceChainConfigs); } @@ -235,7 +222,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 ) public view returns (Internal.MessageExecutionState) { return Internal.MessageExecutionState( ( - s_executionStates[sourceChainSelector][sequenceNumber / 128] + _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber) >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH) ) & MESSAGE_EXECUTION_STATE_MASK ); @@ -252,7 +239,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 Internal.MessageExecutionState newState ) internal { uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH; - uint256 bitmap = s_executionStates[sourceChainSelector][sequenceNumber / 128]; + uint256 bitmap = _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber); // to unset any potential existing state we zero the bits of the section the state occupies, // then we do an AND operation to blank out any existing state for the section. bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset); @@ -262,6 +249,16 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 s_executionStates[sourceChainSelector][sequenceNumber / 128] = bitmap; } + /// @param sourceChainSelector remote source chain selector to get sequence number bitmap for + /// @param sequenceNumber sequence number to get bitmap for + /// @return bitmap Bitmap of the given sequence number for the provided source chain selector. One bitmap represents 128 sequence numbers + function _getSequenceNumberBitmap( + uint64 sourceChainSelector, + uint64 sequenceNumber + ) internal view returns (uint256 bitmap) { + return s_executionStates[sourceChainSelector][sequenceNumber / 128]; + } + /// @inheritdoc IAny2EVMMultiOffRamp function getSenderNonce(uint64 sourceChainSelector, address sender) external view returns (uint64) { (uint64 nonce,) = _getSenderNonce(sourceChainSelector, sender); @@ -304,8 +301,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 uint256[][] memory gasLimitOverrides ) external { // We do this here because the other _execute path is already covered by MultiOCR3Base. - // TODO: contract size golfing - split to internal function - if (i_chainID != block.chainid) revert MultiOCR3Base.ForkedChain(i_chainID, uint64(block.chainid)); + _whenChainNotForked(); uint256 numReports = reports.length; if (numReports != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); @@ -333,19 +329,12 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 /// and expects the exec plugin type to be configured with no signatures. /// @param report serialized execution report function execute(bytes32[3] calldata reportContext, bytes calldata report) external { - _reportExec(report); + _batchExecute(abi.decode(report, (Internal.ExecutionReportSingleChain[])), new uint256[][](0)); - // TODO: gas / contract size saving from CONSTANT? bytes32[] memory emptySigs = new bytes32[](0); _transmit(uint8(Internal.OCRPluginType.Execution), reportContext, report, emptySigs, emptySigs, bytes32("")); } - /// @notice Reporting function for the execution plugin - /// @param encodedReport encoded ExecutionReport - function _reportExec(bytes calldata encodedReport) internal { - _batchExecute(abi.decode(encodedReport, (Internal.ExecutionReportSingleChain[])), new uint256[][](0)); - } - /// @notice Batch executes a set of reports, each report matching one single source chain /// @param reports Set of execution reports (one per chain) containing the messages and proofs /// @param manualExecGasLimits An array of gas limits to use for manual execution @@ -378,18 +367,14 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 uint256[] memory manualExecGasLimits ) internal { uint64 sourceChainSelector = report.sourceChainSelector; - // TODO: re-use isCursed / isUnpaused check from _verify here - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) revert CursedByRMN(sourceChainSelector); + _whenNotCursed(sourceChainSelector); + + SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); uint256 numMsgs = report.messages.length; if (numMsgs == 0) revert EmptyReport(); if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData(); - SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; - if (!sourceChainConfig.isEnabled) { - revert SourceChainNotEnabled(sourceChainSelector); - } - bytes32[] memory hashedLeaves = new bytes32[](numMsgs); for (uint256 i = 0; i < numMsgs; ++i) { @@ -483,16 +468,10 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 // Although we expect only valid messages will be committed, we check again // when executing as a defense in depth measure. - // TODO: GAS GOLF - evaluate caching sequenceNumber instead of offchainTokenData bytes[] memory offchainTokenData = report.offchainTokenData[i]; - _isWellFormed( - message.messageId, - sourceChainSelector, - message.sequenceNumber, - message.tokenAmounts.length, - message.data.length, - offchainTokenData.length - ); + if (message.tokenAmounts.length != offchainTokenData.length) { + revert TokenDataMismatch(sourceChainSelector, message.sequenceNumber); + } _setExecutionState(sourceChainSelector, message.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); @@ -529,30 +508,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 } } - /// @notice Does basic message validation. Should never fail. - /// @param sequenceNumber Sequence number of the message. - /// @param numberOfTokens Length of tokenAmounts array in the message. - /// @param dataLength Length of data field in the message. - /// @param offchainTokenDataLength Length of offchainTokenData array. - /// @dev reverts on validation failures. - function _isWellFormed( - bytes32 messageId, - uint64 sourceChainSelector, - uint64 sequenceNumber, - uint256 numberOfTokens, - uint256 dataLength, - uint256 offchainTokenDataLength - ) private view { - // TODO: move maxNumberOfTokens & data length validation offchain - if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg)) { - revert UnsupportedNumberOfTokens(sourceChainSelector, sequenceNumber); - } - if (numberOfTokens != offchainTokenDataLength) revert TokenDataMismatch(sourceChainSelector, sequenceNumber); - if (dataLength > uint256(s_dynamicConfig.maxDataBytes)) { - revert MessageTooLarge(messageId, uint256(s_dynamicConfig.maxDataBytes), dataLength); - } - } - /// @notice Try executing a message. /// @param message Internal.EVM2EVMMessage memory message. /// @param offchainTokenData Data provided by the DON for token transfers. @@ -597,11 +552,9 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 if (message.tokenAmounts.length > 0) { destTokenAmounts = _releaseOrMintTokens( message.tokenAmounts, - Any2EVMMessageRoute({ - sender: abi.encode(message.sender), - sourceChainSelector: message.sourceChainSelector, - receiver: message.receiver - }), + abi.encode(message.sender), + message.receiver, + message.sourceChainSelector, message.sourceTokenData, offchainTokenData ); @@ -667,79 +620,71 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 bytes32[] calldata ss, bytes32 rawVs // signatures ) external { - _reportCommit(report, uint40(uint256(reportContext[1]))); - _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); - } - - /// @notice Reporting function for the commit plugin - /// @param encodedReport encoded CommitReport - /// @param epochAndRound Epoch and round of the report - function _reportCommit(bytes calldata encodedReport, uint40 epochAndRound) internal whenNotPaused { - CommitReport memory report = abi.decode(encodedReport, (CommitReport)); + CommitReport memory commitReport = abi.decode(report, (CommitReport)); // Check if the report contains price updates - if (report.priceUpdates.tokenPriceUpdates.length > 0 || report.priceUpdates.gasPriceUpdates.length > 0) { + if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) + { + uint64 sequenceNumber = uint64(uint256(reportContext[1])); + // Check for price staleness based on the epoch and round - if (s_latestPriceEpochAndRound < epochAndRound) { + if (s_latestPriceSequenceNumber < sequenceNumber) { // If prices are not stale, update the latest epoch and round - s_latestPriceEpochAndRound = epochAndRound; + s_latestPriceSequenceNumber = sequenceNumber; // And update the prices in the price registry - IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(report.priceUpdates); - - // If there is no root, the report only contained fee updated and - // we return to not revert on the empty root check below. - if (report.merkleRoots.length == 0) return; + IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(commitReport.priceUpdates); } else { // If prices are stale and the report doesn't contain a root, this report // does not have any valid information and we revert. // If it does contain a merkle root, continue to the root checking section. - if (report.merkleRoots.length == 0) revert StaleCommitReport(); + if (commitReport.merkleRoots.length == 0) revert StaleCommitReport(); } } - for (uint256 i = 0; i < report.merkleRoots.length; ++i) { - MerkleRoot memory root = report.merkleRoots[i]; + for (uint256 i = 0; i < commitReport.merkleRoots.length; ++i) { + MerkleRoot memory root = commitReport.merkleRoots[i]; uint64 sourceChainSelector = root.sourceChainSelector; - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) revert CursedByRMN(sourceChainSelector); - - SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; + _whenNotCursed(sourceChainSelector); + SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); - if (!sourceChainConfig.isEnabled) revert SourceChainNotEnabled(sourceChainSelector); // If we reached this section, the report should contain a valid root if (sourceChainConfig.minSeqNr != root.interval.min || root.interval.min > root.interval.max) { revert InvalidInterval(root.sourceChainSelector, root.interval); } // TODO: confirm how RMN offchain blessing impacts commit report - if (root.merkleRoot == bytes32(0)) revert InvalidRoot(); + bytes32 merkleRoot = root.merkleRoot; + if (merkleRoot == bytes32(0)) revert InvalidRoot(); // Disallow duplicate roots as that would reset the timestamp and // delay potential manual execution. - if (s_roots[root.sourceChainSelector][root.merkleRoot] != 0) { - revert RootAlreadyCommitted(root.sourceChainSelector, root.merkleRoot); + if (s_roots[root.sourceChainSelector][merkleRoot] != 0) { + revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot); } sourceChainConfig.minSeqNr = root.interval.max + 1; - s_roots[root.sourceChainSelector][root.merkleRoot] = block.timestamp; + s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; } - emit CommitReportAccepted(report); + emit CommitReportAccepted(commitReport); + + _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); } - /// @notice Returns the epoch and round of the last price update. - /// @return the latest price epoch and round. - function getLatestPriceEpochAndRound() external view returns (uint64) { - return s_latestPriceEpochAndRound; + /// @notice Returns the sequence number of the last price update. + /// @return the latest price sequence number. + function getLatestPriceSequenceNumber() public view returns (uint64) { + return s_latestPriceSequenceNumber; } - /// @notice Sets the latest epoch and round for price update. - /// @param latestPriceEpochAndRound The new epoch and round for prices. - function setLatestPriceEpochAndRound(uint40 latestPriceEpochAndRound) external onlyOwner { - uint40 oldEpochAndRound = s_latestPriceEpochAndRound; + /// @notice Sets the latest sequence number for price update. + /// @param latestPriceSequenceNumber The new sequence number for prices + function setLatestPriceSequenceNumber(uint64 latestPriceSequenceNumber) external onlyOwner { + uint64 oldPriceSequenceNumber = s_latestPriceSequenceNumber; - s_latestPriceEpochAndRound = latestPriceEpochAndRound; + s_latestPriceSequenceNumber = latestPriceSequenceNumber; - emit LatestPriceEpochAndRoundSet(oldEpochAndRound, latestPriceEpochAndRound); + emit LatestPriceSequenceNumberSet(oldPriceSequenceNumber, latestPriceSequenceNumber); } /// @notice Returns the timestamp of a potentially previously committed merkle root. @@ -783,7 +728,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 bytes32[] memory hashedLeaves, bytes32[] memory proofs, uint256 proofFlagBits - ) internal view virtual whenNotPaused returns (uint256 timestamp) { + ) internal view virtual returns (uint256 timestamp) { bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); // Only return non-zero if present and blessed. if (!isBlessed(root)) { @@ -799,7 +744,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 // since epoch and rounds are scoped per config digest. // Note that s_minSeqNr/roots do not need to be reset as the roots persist // across reconfigurations and are de-duplicated separately. - s_latestPriceEpochAndRound = 0; + s_latestPriceSequenceNumber = 0; } } @@ -874,25 +819,115 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 /// @notice Sets the dynamic config. function setDynamicConfig(DynamicConfig memory dynamicConfig) external onlyOwner { - if (dynamicConfig.priceRegistry == address(0)) revert ZeroAddressNotAllowed(); - if (dynamicConfig.router == address(0)) revert ZeroAddressNotAllowed(); + if (dynamicConfig.priceRegistry == address(0) || dynamicConfig.router == address(0)) { + revert ZeroAddressNotAllowed(); + } s_dynamicConfig = dynamicConfig; - // TODO: contract size golfing - is StaticConfig needed in the event? - emit ConfigSet( - StaticConfig({chainSelector: i_chainSelector, rmnProxy: i_rmnProxy, tokenAdminRegistry: i_tokenAdminRegistry}), - dynamicConfig - ); + emit DynamicConfigSet(dynamicConfig); + } + + /// @notice Returns a source chain config with a check that the config is enabled + /// @param sourceChainSelector Source chain selector to check for cursing + /// @return sourceChainConfig Source chain config + function _getEnabledSourceChainConfig(uint64 sourceChainSelector) internal view returns (SourceChainConfig storage) { + SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; + if (!sourceChainConfig.isEnabled) { + revert SourceChainNotEnabled(sourceChainSelector); + } + + return sourceChainConfig; } // ================================================================ // │ Tokens and pools │ // ================================================================ + /// @notice Uses a pool to release or mint a token to a receiver address in two steps. First, the pool is called + /// to release the tokens to the offRamp, then the offRamp calls the token contract to transfer the tokens to the + /// receiver. This is done to ensure the exact number of tokens, the pool claims to release are actually transferred. + /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the + /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by + /// registering the token on this chain, and re-trying the msg. + /// @param sourceAmount The amount of tokens to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceTokenData A struct containing the local token address, the source pool address and optional data + /// returned from the source pool. + /// @param offchainTokenData Data fetched offchain by the DON. + function _releaseOrMintSingleToken( + uint256 sourceAmount, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + Internal.SourceTokenData memory sourceTokenData, + bytes memory offchainTokenData + ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { + // We need to safely decode the token address from the sourceTokenData, as it could be wrong, + // in which case it doesn't have to be a valid EVM address. + address localToken = Internal._validateEVMAddress(sourceTokenData.destTokenAddress); + // We check with the token admin registry if the token has a pool on this chain. + address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); + // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. + // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. + // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should + // account for 90k gas overhead due to the interface check. + if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { + revert NotACompatiblePool(localPoolAddress); + } + + // We determined that the pool address is a valid EVM address, but that does not mean the code at this + // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location + // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. + // We call the pool with exact gas to increase resistance against malicious tokens or token pools. + // We protects against return data bombs by capping the return data size at MAX_RET_BYTES. + (bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( + abi.encodeWithSelector( + IPoolV1.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: receiver, + amount: sourceAmount, + localToken: localToken, + remoteChainSelector: sourceChainSelector, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ), + localPoolAddress, + s_dynamicConfig.maxPoolReleaseOrMintGas, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + + // wrap and rethrow the error so we can catch it lower in the stack + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should be the local token address. + if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { + revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); + } + uint256 localAmount = abi.decode(returnData, (uint256)); + // Since token pools send the tokens to the msg.sender, which is this offRamp, we need to + // transfer them to the final receiver. We use the _callWithExactGasSafeReturnData function because + // the token contracts are not considered trusted. + (success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( + abi.encodeWithSelector(IERC20.transfer.selector, receiver, localAmount), + localToken, + s_dynamicConfig.maxTokenTransferGas, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + + if (!success) revert TokenHandlingError(returnData); + + return Client.EVMTokenAmount({token: localToken, amount: localAmount}); + } + /// @notice Uses pools to release or mint a number of different tokens to a receiver address. /// @param sourceTokenAmounts List of tokens and amount values to be released/minted. - /// @param messageRoute Message route details (original sender, receiver and source chain) /// @param encodedSourceTokenData Array of token data returned by token pools on the source chain. /// @param offchainTokenData Array of token data fetched offchain by the DON. /// @dev This function wrappes the token pool call in a try catch block to gracefully handle @@ -900,83 +935,30 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. function _releaseOrMintTokens( Client.EVMTokenAmount[] memory sourceTokenAmounts, - Any2EVMMessageRoute memory messageRoute, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, bytes[] memory encodedSourceTokenData, bytes[] memory offchainTokenData ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { // Creating a copy is more gas efficient than initializing a new array. destTokenAmounts = sourceTokenAmounts; for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { - // This should never revert as the onRamp creates the sourceTokenData. Only the inner components from - // this struct come from untrusted sources. - Internal.SourceTokenData memory sourceTokenData = - abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData)); - // We need to safely decode the pool address from the sourceTokenData, as it could be wrong, - // in which case it doesn't have to be a valid EVM address. - address localToken = Internal._validateEVMAddress(sourceTokenData.destTokenAddress); - // We check with the token admin registry if the token has a pool on this chain. - address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); - // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. - // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. - // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should - // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { - revert NotACompatiblePool(localPoolAddress); - } - - // We determined that the pool address is a valid EVM address, but that does not mean the code at this - // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location - // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. - // We call the pool with exact gas to increase resistance against malicious tokens or token pools. - // We protects against return data bombs by capping the return data size at MAX_RET_BYTES. - (bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeWithSelector( - IPoolV1.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: messageRoute.sender, - receiver: messageRoute.receiver, - amount: sourceTokenAmounts[i].amount, - localToken: localToken, - remoteChainSelector: messageRoute.sourceChainSelector, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData[i] - }) - ), - localPoolAddress, - s_dynamicConfig.maxPoolReleaseOrMintGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - // wrap and rethrow the error so we can catch it lower in the stack - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should be the local token address. - if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { - revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); - } - uint256 amount = abi.decode(returnData, (uint256)); - - (success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeWithSelector(IERC20.transfer.selector, messageRoute.receiver, amount), - localToken, - s_dynamicConfig.maxTokenTransferGas, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES + destTokenAmounts[i] = _releaseOrMintSingleToken( + sourceTokenAmounts[i].amount, + originalSender, + receiver, + sourceChainSelector, + abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData)), + offchainTokenData[i] ); - - if (!success) revert TokenHandlingError(returnData); - - destTokenAmounts[i].token = localToken; - destTokenAmounts[i].amount = amount; } return destTokenAmounts; } // ================================================================ - // │ Access │ + // │ Access and RMN │ // ================================================================ /// @notice Reverts as this contract should not access CCIP messages @@ -985,34 +967,11 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, MultiOCR3 revert(); } - /// @notice Single function to check the status of the commitStore. - function isUnpausedAndNotCursed(uint64 sourceChainSelector) external view returns (bool) { - return !IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector))) && !s_paused; - } - - // TODO: global pausing can be removed delegated to the i_rmnProxy - /// @notice Modifier to make a function callable only when the contract is not paused. - modifier whenNotPaused() { - if (paused()) revert PausedError(); - _; - } - - /// @notice Returns true if the contract is paused, and false otherwise. - function paused() public view returns (bool) { - return s_paused; - } - - /// @notice Pause the contract - /// @dev only callable by the owner - function pause() external onlyOwner { - s_paused = true; - emit Paused(msg.sender); - } - - /// @notice Unpause the contract - /// @dev only callable by the owner - function unpause() external onlyOwner { - s_paused = false; - emit Unpaused(msg.sender); + /// @notice Validates that the source chain -> this chain lane, and reverts if it is cursed + /// @param sourceChainSelector Source chain selector to check for cursing + function _whenNotCursed(uint64 sourceChainSelector) internal view { + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { + revert CursedByRMN(sourceChainSelector); + } } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 2db164eaf4..3ab36ab469 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -138,10 +138,8 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - bytes memory commitReport = abi.encode(report); - vm.resumeGasMetering(); - s_offRamp.reportCommit(commitReport, ++s_latestEpochAndRound); + _commit(report, ++s_latestSequenceNumber); vm.pauseGasMetering(); bytes32[] memory proofs = new bytes32[](0); diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol index 9d0c5d14f5..83b9569425 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol @@ -30,13 +30,30 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { return _metadataHash(sourceChainSelector, onRamp, Internal.EVM_2_EVM_MESSAGE_HASH); } + function releaseOrMintSingleToken( + uint256 sourceTokenAmount, + bytes calldata originalSender, + address receiver, + uint64 sourceChainSelector, + Internal.SourceTokenData calldata sourceTokenData, + bytes calldata offchainTokenData + ) external returns (Client.EVMTokenAmount memory) { + return _releaseOrMintSingleToken( + sourceTokenAmount, originalSender, receiver, sourceChainSelector, sourceTokenData, offchainTokenData + ); + } + function releaseOrMintTokens( Client.EVMTokenAmount[] memory sourceTokenAmounts, - EVM2EVMMultiOffRamp.Any2EVMMessageRoute memory messageRoute, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, bytes[] calldata sourceTokenData, bytes[] calldata offchainTokenData ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens(sourceTokenAmounts, messageRoute, sourceTokenData, offchainTokenData); + return _releaseOrMintTokens( + sourceTokenAmounts, originalSender, receiver, sourceChainSelector, sourceTokenData, offchainTokenData + ); } function trialExecute( @@ -46,14 +63,6 @@ contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { return _trialExecute(message, offchainTokenData); } - function reportExec(bytes calldata executableReports) external { - _reportExec(executableReports); - } - - function reportCommit(bytes calldata commitReport, uint40 epochAndRound) external { - _reportCommit(commitReport, epochAndRound); - } - function executeSingleReport( Internal.ExecutionReportSingleChain memory rep, uint256[] memory manualExecGasLimits diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol index b937fb9ff5..5b784bf721 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol @@ -24,7 +24,6 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: s_configDigest1, F: 1, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -33,7 +32,6 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { ocrPluginType: 1, configDigest: s_configDigest2, F: 2, - uniqueReports: true, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -42,7 +40,6 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { ocrPluginType: 2, configDigest: s_configDigest3, F: 1, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters @@ -51,42 +48,24 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TransmitSignersNonUniqueReports_gas_Success() public { + function test_TransmitSigners_gas_Success() public { vm.pauseGasMetering(); bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // F = 2, need 2 signatures (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest1, REPORT, 2); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); s_multiOCR3.setTransmitOcrPluginType(0); vm.expectEmit(); - emit MultiOCR3Base.Transmitted(0, s_configDigest1, uint32(uint256(s_configDigest1) >> 8)); + emit MultiOCR3Base.Transmitted(0, s_configDigest1, uint64(uint256(s_configDigest1))); vm.startPrank(s_validTransmitters[1]); vm.resumeGasMetering(); s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_TransmitUniqueReportSigners_gas_Success() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest2, s_configDigest2, s_configDigest2]; - - // F = 1, need 5 signatures - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest2, REPORT, 5); - - s_multiOCR3.setTransmitOcrPluginType(1); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(1, s_configDigest2, uint32(uint256(s_configDigest2) >> 8)); - - vm.startPrank(s_validTransmitters[2]); - vm.resumeGasMetering(); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - function test_TransmitWithoutSignatureVerification_gas_Success() public { vm.pauseGasMetering(); bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; @@ -94,18 +73,14 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.setTransmitOcrPluginType(2); vm.expectEmit(); - emit MultiOCR3Base.Transmitted(2, s_configDigest3, uint32(uint256(s_configDigest3) >> 8)); + emit MultiOCR3Base.Transmitted(2, s_configDigest3, uint64(uint256(s_configDigest3))); vm.startPrank(s_validTransmitters[0]); vm.resumeGasMetering(); s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); } - function test_Fuzz_TransmitSignersWithSignatures_Success( - uint8 F, - uint64 randomAddressOffset, - bool uniqueReports - ) public { + function test_Fuzz_TransmitSignersWithSignatures_Success(uint8 F, uint64 randomAddressOffset) public { vm.pauseGasMetering(); F = uint8(bound(F, 1, 3)); @@ -133,7 +108,6 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { ocrPluginType: 3, configDigest: s_configDigest1, F: F, - uniqueReports: uniqueReports, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -147,7 +121,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // condition: matches signature expectation for transmit - uint8 numSignatures = uniqueReports ? ((signersLength + F) / 2 + 1) : (F + 1); + uint8 numSignatures = F + 1; uint256[] memory pickedSignerKeys = new uint256[](numSignatures); // Randomise picked signers with random offset @@ -156,10 +130,10 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(pickedSignerKeys, s_configDigest1, REPORT, numSignatures); + _getSignaturesForDigest(pickedSignerKeys, REPORT, reportContext, numSignatures); vm.expectEmit(); - emit MultiOCR3Base.Transmitted(3, s_configDigest1, uint32(uint256(s_configDigest1) >> 8)); + emit MultiOCR3Base.Transmitted(3, s_configDigest1, uint64(uint256(s_configDigest1))); vm.resumeGasMetering(); s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); @@ -170,7 +144,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest1, REPORT, 2); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); s_multiOCR3.setTransmitOcrPluginType(0); @@ -198,7 +172,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // 1 signature too many (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest2, REPORT, 6); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 6); s_multiOCR3.setTransmitOcrPluginType(1); @@ -212,7 +186,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Missing 1 signature for unique report (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest2, REPORT, 4); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 4); s_multiOCR3.setTransmitOcrPluginType(1); @@ -225,7 +199,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { bytes32 configDigest; bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, s_configDigest1, REPORT, 2); + (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); s_multiOCR3.setTransmitOcrPluginType(0); @@ -261,7 +235,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest1, REPORT, 2); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); rs[1] = rs[0]; ss[1] = ss[0]; @@ -279,7 +253,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigest1, REPORT, 2); + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); rs[0] = s_configDigest1; ss = rs; @@ -367,7 +341,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -392,7 +365,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: uint8(ocrConfigs[0].signers.length), - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: s_validSigners, @@ -412,7 +384,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, signers, s_validTransmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: signers, transmitters: s_validTransmitters @@ -437,7 +408,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: uint8(ocrConfigs[0].signers.length), - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: signers, @@ -456,7 +426,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, new address[](0), s_validTransmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_validSigners, transmitters: s_validTransmitters @@ -481,7 +450,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: 0, - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: s_emptySigners, @@ -506,7 +474,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), F: 2, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -515,7 +482,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 1, configDigest: _getBasicConfigDigest(1, s_validSigners, s_validTransmitters), F: 1, - uniqueReports: true, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -524,7 +490,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 2, configDigest: _getBasicConfigDigest(1, s_partialSigners, s_partialTransmitters), F: 1, - uniqueReports: true, isSignatureVerificationEnabled: true, signers: s_partialSigners, transmitters: s_partialTransmitters @@ -551,7 +516,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[i].configDigest, F: ocrConfigs[i].F, n: uint8(ocrConfigs[i].signers.length), - uniqueReports: ocrConfigs[i].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[i].isSignatureVerificationEnabled }), signers: ocrConfigs[i].signers, @@ -617,7 +581,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfig.configDigest, F: ocrConfig.F, n: ocrConfig.isSignatureVerificationEnabled ? uint8(ocrConfig.signers.length) : 0, - uniqueReports: ocrConfig.uniqueReports, isSignatureVerificationEnabled: ocrConfig.isSignatureVerificationEnabled }), signers: ocrConfig.signers, @@ -634,7 +597,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(1, s_emptySigners, s_validTransmitters), F: 1, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters @@ -665,7 +627,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: uint8(ocrConfigs[0].signers.length), - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: s_emptySigners, @@ -695,7 +656,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), F: 2, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -728,7 +688,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: uint8(ocrConfigs[0].signers.length), - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: newSigners, @@ -769,7 +728,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(1, signers, transmitters), F: 1, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -793,7 +751,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(1, signers, transmitters), F: 1, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -823,7 +780,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, signers, transmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -849,7 +805,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, signers, transmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -869,7 +824,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), F: F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -877,13 +831,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); - // uniqueReports cannot change - ocrConfigs[0].uniqueReports = true; - vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.StaticConfigCannotBeChanged.selector, 0)); - s_multiOCR3.setOCR3Configs(ocrConfigs); - // signature verification cannot change - ocrConfigs[0].uniqueReports = false; ocrConfigs[0].isSignatureVerificationEnabled = false; vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.StaticConfigCannotBeChanged.selector, 0)); s_multiOCR3.setOCR3Configs(ocrConfigs); @@ -898,7 +846,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(1, signers, transmitters), F: 1, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: transmitters @@ -916,7 +863,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(0, s_validSigners, s_validTransmitters), F: 0, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -939,7 +885,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(10, signers, transmitters), F: 10, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: signers, transmitters: transmitters @@ -961,7 +906,6 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ocrPluginType: 0, configDigest: _getBasicConfigDigest(1, signers, s_validTransmitters), F: 1, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: signers, transmitters: s_validTransmitters diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol index 3fb2b4a9fc..6f6219bc9b 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol @@ -71,13 +71,6 @@ contract MultiOCR3BaseSetup is BaseTest { return bytes32((prefix & prefixMask) | (h & ~prefixMask)); } - /// @dev returns a hash value in the same format as the h value on which the signature verified - /// in the _transmit function - function _getReportDigest(bytes32 configDigest, bytes memory report) internal pure returns (bytes32) { - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - return keccak256(abi.encodePacked(keccak256(report), reportContext)); - } - function _assertOCRConfigEquality( MultiOCR3Base.OCRConfig memory configA, MultiOCR3Base.OCRConfig memory configB @@ -85,7 +78,6 @@ contract MultiOCR3BaseSetup is BaseTest { vm.assertEq(configA.configInfo.configDigest, configB.configInfo.configDigest); vm.assertEq(configA.configInfo.F, configB.configInfo.F); vm.assertEq(configA.configInfo.n, configB.configInfo.n); - vm.assertEq(configA.configInfo.uniqueReports, configB.configInfo.uniqueReports); vm.assertEq(configA.configInfo.isSignatureVerificationEnabled, configB.configInfo.isSignatureVerificationEnabled); vm.assertEq(configA.signers, configB.signers); @@ -100,17 +92,19 @@ contract MultiOCR3BaseSetup is BaseTest { function _getSignaturesForDigest( uint256[] memory signerPrivateKeys, - bytes32 configDigest, bytes memory report, + bytes32[3] memory reportContext, uint8 signatureCount ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { rs = new bytes32[](signatureCount); ss = new bytes32[](signatureCount); vs = new uint8[](signatureCount); + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + // Calculate signatures for (uint256 i; i < signatureCount; ++i) { - (vs[i], rs[i], ss[i]) = vm.sign(signerPrivateKeys[i], _getReportDigest(configDigest, report)); + (vs[i], rs[i], ss[i]) = vm.sign(signerPrivateKeys[i], reportDigest); rawVs = rawVs | (bytes32(bytes1(vs[i] - 27)) >> (8 * i)); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index 345d6af494..39dc2b61df 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.24; import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; +import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; import {PriceRegistry} from "../../PriceRegistry.sol"; @@ -76,6 +76,9 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { metadataHash: s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1 + 1, sourceChainConfigs[1].onRamp) }); + vm.expectEmit(); + emit EVM2EVMMultiOffRamp.StaticConfigSet(staticConfig); + vm.expectEmit(); emit EVM2EVMMultiOffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); @@ -95,7 +98,6 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { ocrPluginType: uint8(Internal.OCRPluginType.Execution), configDigest: s_configDigestExec, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters @@ -120,7 +122,6 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { configDigest: ocrConfigs[0].configDigest, F: ocrConfigs[0].F, n: 0, - uniqueReports: ocrConfigs[0].uniqueReports, isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled }), signers: s_emptySigners, @@ -139,9 +140,7 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { // OffRamp initial values assertEq("EVM2EVMMultiOffRamp 1.6.0-dev", s_offRamp.typeAndVersion()); assertEq(OWNER, s_offRamp.owner()); - assertEq(0, s_offRamp.getLatestPriceEpochAndRound()); - assertTrue(s_offRamp.isUnpausedAndNotCursed(sourceChainConfigs[0].sourceChainSelector)); - assertTrue(s_offRamp.isUnpausedAndNotCursed(sourceChainConfigs[1].sourceChainSelector)); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); } // Revert @@ -255,12 +254,11 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { function test_SetDynamicConfig_Success() public { - EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ConfigSet(staticConfig, dynamicConfig); + emit EVM2EVMMultiOffRamp.DynamicConfigSet(dynamicConfig); s_offRamp.setDynamicConfig(dynamicConfig); @@ -269,13 +267,12 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { } function test_SetDynamicConfigWithValidator_Success() public { - EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = _generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); dynamicConfig.messageValidator = address(s_messageValidator); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ConfigSet(staticConfig, dynamicConfig); + emit EVM2EVMMultiOffRamp.DynamicConfigSet(dynamicConfig); s_offRamp.setDynamicConfig(dynamicConfig); @@ -830,22 +827,6 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0)); } - function test_UnsupportedNumberOfTokens_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Client.EVMTokenAmount[] memory newTokens = new Client.EVMTokenAmount[](MAX_TOKENS_LENGTH + 1); - messages[0].tokenAmounts = newTokens; - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.UnsupportedNumberOfTokens.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].sequenceNumber - ) - ); - s_offRamp.executeSingleReport(report, new uint256[](0)); - } - function test_TokenDataMismatch_Revert() public { Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -860,22 +841,6 @@ contract EVM2EVMMultiOffRamp_executeSingleReport is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleReport(report, new uint256[](0)); } - function test_MessageTooLarge_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].data = new bytes(MAX_DATA_SIZE + 1); - messages[0].messageId = - Internal._hash(messages[0], s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); - - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOffRamp.MessageTooLarge.selector, messages[0].messageId, MAX_DATA_SIZE, messages[0].data.length - ) - ); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); - } - function test_RouterYULCall_Revert() public { Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -1972,7 +1937,7 @@ contract EVM2EVMMultiOffRamp_manuallyExecute is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_reportExec is EVM2EVMMultiOffRampSetup { +contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -1993,7 +1958,13 @@ contract EVM2EVMMultiOffRamp_reportExec is EVM2EVMMultiOffRampSetup { Internal.MessageExecutionState.SUCCESS, "" ); - s_offRamp.reportExec(abi.encode(reports)); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + _execute(reports); } function test_MultipleReports_Success() public { @@ -2035,7 +2006,12 @@ contract EVM2EVMMultiOffRamp_reportExec is EVM2EVMMultiOffRampSetup { "" ); - s_offRamp.reportExec(abi.encode(reports)); + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + _execute(reports); } function test_LargeBatch_Success() public { @@ -2062,7 +2038,12 @@ contract EVM2EVMMultiOffRamp_reportExec is EVM2EVMMultiOffRampSetup { } } - s_offRamp.reportExec(abi.encode(reports)); + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + _execute(reports); } function test_MultipleReportsWithPartialValidationFailures_Success() public { @@ -2119,66 +2100,12 @@ contract EVM2EVMMultiOffRamp_reportExec is EVM2EVMMultiOffRampSetup { ) ); - s_offRamp.reportExec(abi.encode(reports)); - } - - // Reverts - - function test_ZeroReports_Revert() public { - Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](0); - - vm.expectRevert(EVM2EVMMultiOffRamp.EmptyReport.selector); - s_offRamp.reportExec(abi.encode(reports)); - } - - function test_IncorrectArrayType_Revert() public { - uint256[] memory wrongData = new uint256[](1); - wrongData[0] = 1; - - vm.expectRevert(); - s_offRamp.reportExec(abi.encode(wrongData)); - } - - function test_NonArray_Revert() public { - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert(); - s_offRamp.reportExec(abi.encode(report)); - } -} - -contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - } - - // Asserts that execute completes - function test_SingleReport_Success() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReportSingleChain[] memory reports = - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.ExecutionStateChanged( - SOURCE_CHAIN_SELECTOR_1, - messages[0].sequenceNumber, - messages[0].messageId, - Internal.MessageExecutionState.SUCCESS, - "" - ); - vm.expectEmit(); emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint32(uint256(s_configDigestExec) >> 8) + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) ); - vm.startPrank(s_validTransmitters[0]); - s_offRamp.execute(reportContext, abi.encode(reports)); + _execute(reports); } // Reverts @@ -2198,12 +2125,12 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); s_offRamp.execute(reportContext, abi.encode(reports)); @@ -2218,19 +2145,18 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { ocrPluginType: uint8(Internal.OCRPluginType.Commit), configDigest: s_configDigestCommit, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters }); s_offRamp.setOCR3Configs(ocrConfigs); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + vm.startPrank(s_validTransmitters[0]); vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); s_offRamp.execute(reportContext, abi.encode(reports)); @@ -2247,22 +2173,47 @@ contract EVM2EVMMultiOffRamp_execute is EVM2EVMMultiOffRampSetup { ocrPluginType: uint8(Internal.OCRPluginType.Execution), configDigest: s_configDigestExec, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters }); s_offRamp.setOCR3Configs(ocrConfigs); - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + vm.expectRevert(); + _execute(reports); + } + + function test_ZeroReports_Revert() public { + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](0); + + vm.expectRevert(EVM2EVMMultiOffRamp.EmptyReport.selector); + _execute(reports); + } + + function test_IncorrectArrayType_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + uint256[] memory wrongData = new uint256[](1); + wrongData[0] = 1; + vm.startPrank(s_validTransmitters[0]); vm.expectRevert(); - s_offRamp.execute(reportContext, abi.encode(reports)); + s_offRamp.execute(reportContext, abi.encode(wrongData)); + } + + function test_NonArray_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.execute(reportContext, abi.encode(report)); } } @@ -2544,18 +2495,125 @@ contract EVM2EVMMultiOffRamp_trialExecute is EVM2EVMMultiOffRampSetup { } } -contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { - EVM2EVMMultiOffRamp.Any2EVMMessageRoute internal MESSAGE_ROUTE; - +contract EVM2EVMMultiOffRamp__releaseOrMintSingleToken is EVM2EVMMultiOffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); + } - MESSAGE_ROUTE = EVM2EVMMultiOffRamp.Any2EVMMessageRoute({ - sender: abi.encode(OWNER), - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - receiver: OWNER + function test__releaseOrMintSingleToken_Success() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + extraData: "" }); + + vm.expectCall( + s_destPoolBySourceToken[token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: OWNER, + amount: amount, + localToken: s_destTokenBySourceToken[token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ) + ); + + s_offRamp.releaseOrMintSingleToken( + amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + ); + + assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); + } + + function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + address destToken = s_destTokenBySourceToken[token]; + vm.label(destToken, "destToken"); + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: abi.encode(destToken), + extraData: "" + }); + + // Address(0) should always revert + address returnedPool = address(0); + + vm.mockCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), + abi.encode(returnedPool) + ); + + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); + + s_offRamp.releaseOrMintSingleToken( + amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + ); + + // A contract that doesn't support the interface should also revert + returnedPool = address(s_offRamp); + + vm.mockCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), + abi.encode(returnedPool) + ); + + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, returnedPool)); + + s_offRamp.releaseOrMintSingleToken( + amount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + ); + } + + function test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() public { + address receiver = makeAddr("receiver"); + uint256 amount = 123123; + address token = s_sourceTokens[0]; + address destToken = s_destTokenBySourceToken[token]; + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: abi.encode(destToken), + extraData: "" + }); + + bytes memory revertData = "call reverted :o"; + + vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); + + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, revertData)); + s_offRamp.releaseOrMintSingleToken( + amount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + ); + } +} + +contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); } function test_releaseOrMintTokens_Success() public { @@ -2576,11 +2634,11 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ - originalSender: MESSAGE_ROUTE.sender, - receiver: MESSAGE_ROUTE.receiver, + originalSender: abi.encode(OWNER), + receiver: OWNER, amount: srcTokenAmounts[0].amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: MESSAGE_ROUTE.sourceChainSelector, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: sourceTokenData.sourcePoolAddress, sourcePoolData: sourceTokenData.extraData, offchainTokenData: offchainTokenData[0] @@ -2588,7 +2646,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ) ); - s_offRamp.releaseOrMintTokens(srcTokenAmounts, MESSAGE_ROUTE, encodedSourceTokenData, offchainTokenData); + s_offRamp.releaseOrMintTokens( + srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + ); assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } @@ -2612,11 +2672,11 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ - originalSender: MESSAGE_ROUTE.sender, - receiver: MESSAGE_ROUTE.receiver, + originalSender: abi.encode(OWNER), + receiver: OWNER, amount: amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: MESSAGE_ROUTE.sourceChainSelector, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: sourceTokenData.sourcePoolAddress, sourcePoolData: sourceTokenData.extraData, offchainTokenData: offchainTokenData[0] @@ -2625,8 +2685,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encode(amount * destinationDenominationMultiplier) ); - Client.EVMTokenAmount[] memory destTokenAmounts = - s_offRamp.releaseOrMintTokens(srcTokenAmounts, MESSAGE_ROUTE, encodedSourceTokenData, offchainTokenData); + Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( + srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + ); assertEq(destTokenAmounts[0].amount, amount * destinationDenominationMultiplier); assertEq(destTokenAmounts[0].token, destToken); @@ -2643,7 +2704,12 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, unknownError)); s_offRamp.releaseOrMintTokens( - srcTokenAmounts, MESSAGE_ROUTE, _getDefaultSourceTokenData(srcTokenAmounts), new bytes[](srcTokenAmounts.length) + srcTokenAmounts, + abi.encode(OWNER), + OWNER, + SOURCE_CHAIN_SELECTOR_1, + _getDefaultSourceTokenData(srcTokenAmounts), + new bytes[](srcTokenAmounts.length) ); } @@ -2661,11 +2727,11 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ - originalSender: MESSAGE_ROUTE.sender, - receiver: MESSAGE_ROUTE.receiver, + originalSender: abi.encode(OWNER), + receiver: OWNER, amount: amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: MESSAGE_ROUTE.sourceChainSelector, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: sourceTokenData.sourcePoolAddress, sourcePoolData: sourceTokenData.extraData, offchainTokenData: offchainTokenData[0] @@ -2679,7 +2745,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64) ); - s_offRamp.releaseOrMintTokens(srcTokenAmounts, MESSAGE_ROUTE, encodedSourceTokenData, offchainTokenData); + s_offRamp.releaseOrMintTokens( + srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, encodedSourceTokenData, offchainTokenData + ); } function test_releaseOrMintTokens_InvalidEVMAddress_Revert() public { @@ -2699,40 +2767,11 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); - s_offRamp.releaseOrMintTokens(srcTokenAmounts, MESSAGE_ROUTE, sourceTokenData, offchainTokenData); + s_offRamp.releaseOrMintTokens( + srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, offchainTokenData + ); } - // TODO: re-add after ARL changes - // function test_RateLimitErrors_Reverts() public { - // Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - // bytes[] memory rateLimitErrors = new bytes[](5); - // rateLimitErrors[0] = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - // rateLimitErrors[1] = - // abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, uint256(100), uint256(1000)); - // rateLimitErrors[2] = - // abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, uint256(42), 1, s_sourceTokens[0]); - // rateLimitErrors[3] = abi.encodeWithSelector( - // RateLimiter.TokenMaxCapacityExceeded.selector, uint256(100), uint256(1000), s_sourceTokens[0] - // ); - // rateLimitErrors[4] = - // abi.encodeWithSelector(RateLimiter.TokenRateLimitReached.selector, uint256(42), 1, s_sourceTokens[0]); - - // for (uint256 i = 0; i < rateLimitErrors.length; ++i) { - // s_maybeRevertingPool.setShouldRevert(rateLimitErrors[i]); - - // vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.TokenHandlingError.selector, rateLimitErrors[i])); - - // s_offRamp.releaseOrMintTokens( - // srcTokenAmounts, - // abi.encode(OWNER), - // OWNER, - // _getDefaultSourceTokenData(srcTokenAmounts), - // new bytes[](srcTokenAmounts.length) - // ); - // } - // } - function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); @@ -2747,7 +2786,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens(new Client.EVMTokenAmount[](1), MESSAGE_ROUTE, sourceTokenData, new bytes[](1)); + s_offRamp.releaseOrMintTokens( + new Client.EVMTokenAmount[](1), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, new bytes[](1) + ); } function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { @@ -2761,22 +2802,16 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { bytes[] memory encodedSourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); Internal.SourceTokenData memory sourceTokenData = abi.decode(encodedSourceTokenData[0], (Internal.SourceTokenData)); - EVM2EVMMultiOffRamp.Any2EVMMessageRoute memory messageRouteChain3 = EVM2EVMMultiOffRamp.Any2EVMMessageRoute({ - sender: abi.encode(OWNER), - sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, - receiver: OWNER - }); - vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], abi.encodeWithSelector( LockReleaseTokenPool.releaseOrMint.selector, Pool.ReleaseOrMintInV1({ - originalSender: messageRouteChain3.sender, - receiver: messageRouteChain3.receiver, + originalSender: abi.encode(OWNER), + receiver: OWNER, amount: srcTokenAmounts[0].amount, localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: messageRouteChain3.sourceChainSelector, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_3, sourcePoolAddress: sourceTokenData.sourcePoolAddress, sourcePoolData: sourceTokenData.extraData, offchainTokenData: offchainTokenData[0] @@ -2784,7 +2819,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { ) ); vm.expectRevert(); - s_offRamp.releaseOrMintTokens(srcTokenAmounts, messageRouteChain3, encodedSourceTokenData, offchainTokenData); + s_offRamp.releaseOrMintTokens( + srcTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, encodedSourceTokenData, offchainTokenData + ); } /// forge-config: default.fuzz.runs = 32 @@ -2804,8 +2841,9 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { }) ); - try s_offRamp.releaseOrMintTokens(new Client.EVMTokenAmount[](1), MESSAGE_ROUTE, sourceTokenData, new bytes[](1)) {} - catch (bytes memory reason) { + try s_offRamp.releaseOrMintTokens( + new Client.EVMTokenAmount[](1), abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, sourceTokenData, new bytes[](1) + ) {} catch (bytes memory reason) { // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp assertTrue( bytes4(reason) == EVM2EVMMultiOffRamp.TokenHandlingError.selector @@ -3095,55 +3133,30 @@ contract EVM2EVMMultiOffRamp_applySourceChainConfigUpdates is EVM2EVMMultiOffRam } } -contract EVM2EVMMultiOffRamp_isUnpausedAndRMNHealthy is EVM2EVMMultiOffRampSetup { - function test_RMN_Success() public { - // Test pausing - assertFalse(s_offRamp.paused()); - assertTrue(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - s_offRamp.pause(); - assertTrue(s_offRamp.paused()); - assertFalse(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - s_offRamp.unpause(); - assertFalse(s_offRamp.paused()); - assertTrue(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - // Test rmn - s_mockRMN.voteToCurse(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - assertFalse(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - RMN.UnvoteToCurseRecord[] memory records = new RMN.UnvoteToCurseRecord[](1); - records[0] = RMN.UnvoteToCurseRecord({curseVoteAddr: OWNER, cursesHash: bytes32(uint256(0)), forceUnvote: true}); - s_mockRMN.ownerUnvoteToCurse(records); - assertTrue(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - s_mockRMN.voteToCurse(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - s_offRamp.pause(); - assertFalse(s_offRamp.isUnpausedAndNotCursed(SOURCE_CHAIN_SELECTOR)); - } -} - -contract EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound is EVM2EVMMultiOffRampSetup { - function test_SetLatestPriceEpochAndRound_Success() public { - uint40 latestRoundAndEpoch = 1782155; +contract EVM2EVMMultiOffRamp_setLatestPriceSequenceNumber is EVM2EVMMultiOffRampSetup { + function test_setLatestPriceSequenceNumber_Success() public { + uint64 latestSequenceNumber = 1782155; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.LatestPriceEpochAndRoundSet( - uint40(s_offRamp.getLatestPriceEpochAndRound()), latestRoundAndEpoch + emit EVM2EVMMultiOffRamp.LatestPriceSequenceNumberSet( + s_offRamp.getLatestPriceSequenceNumber(), latestSequenceNumber ); - s_offRamp.setLatestPriceEpochAndRound(latestRoundAndEpoch); - assertEq(s_offRamp.getLatestPriceEpochAndRound(), latestRoundAndEpoch); + s_offRamp.setLatestPriceSequenceNumber(latestSequenceNumber); + assertEq(s_offRamp.getLatestPriceSequenceNumber(), latestSequenceNumber); } function test_PriceEpochCleared_Success() public { // Set latest price epoch and round to non-zero. - uint40 latestEpochAndRound = 1782155; - s_offRamp.setLatestPriceEpochAndRound(latestEpochAndRound); - assertEq(latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + uint64 latestSequenceNumber = 1782155; + s_offRamp.setLatestPriceSequenceNumber(latestSequenceNumber); + assertEq(latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: uint8(Internal.OCRPluginType.Execution), configDigest: s_configDigestExec, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters @@ -3151,14 +3164,13 @@ contract EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound is EVM2EVMMultiOffRampS s_offRamp.setOCR3Configs(ocrConfigs); // Execution plugin OCR config should not clear latest epoch and round - assertEq(latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); // Commit plugin config should clear latest epoch & round ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: uint8(Internal.OCRPluginType.Commit), configDigest: s_configDigestCommit, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -3166,7 +3178,7 @@ contract EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound is EVM2EVMMultiOffRampS s_offRamp.setOCR3Configs(ocrConfigs); // Assert cleared. - assertEq(0, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); } // Reverts @@ -3174,67 +3186,60 @@ contract EVM2EVMMultiOffRamp_setLatestPriceEpochAndRound is EVM2EVMMultiOffRampS function test_OnlyOwner_Revert() public { vm.stopPrank(); vm.expectRevert("Only callable by owner"); - s_offRamp.setLatestPriceEpochAndRound(6723); + s_offRamp.setLatestPriceSequenceNumber(6723); } } -contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { +contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { + uint64 internal s_maxInterval = 12; + function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); - } - function test_ReportOnlyRootSuccess_gas() public { - vm.pauseGasMetering(); - uint64 max1 = 931; - bytes32 root = "Only a single root"; - - EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); - roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: EVM2EVMMultiOffRamp.Interval(1, max1), - merkleRoot: root - }); + s_latestSequenceNumber = uint64(uint256(s_configDigestCommit)); + } - EVM2EVMMultiOffRamp.CommitReport memory report = - EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + function test_ReportAndPriceUpdate_Success() public { + EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(report); + emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); - bytes memory encodedReport = abi.encode(report); + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - vm.resumeGasMetering(); - s_offRamp.reportCommit(encodedReport, ++s_latestEpochAndRound); - vm.pauseGasMetering(); + _commit(commitReport, s_latestSequenceNumber); - assertEq(max1 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); - vm.resumeGasMetering(); + assertEq(s_maxInterval + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } - function test_ReportAndPriceUpdate_Success() public { - uint64 max1 = 12; + function test_ReportOnlyRootSuccess_gas() public { + uint64 max1 = 931; + bytes32 root = "Only a single root"; EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, interval: EVM2EVMMultiOffRamp.Interval(1, max1), - merkleRoot: "test #2" + merkleRoot: root }); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ - priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots - }); + EVM2EVMMultiOffRamp.CommitReport memory commitReport = + EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(report); + emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); assertEq(max1 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); } function test_StaleReportWithRoot_Success() public { @@ -3248,22 +3253,33 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: EVM2EVMMultiOffRamp.Interval(1, maxSeq), merkleRoot: "stale report 1" }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(report); - s_offRamp.reportCommit(abi.encode(report), s_latestEpochAndRound); + emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + + commitReport.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(maxSeq + 1, maxSeq * 2); + commitReport.merkleRoots[0].merkleRoot = "stale report 2"; - report.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(maxSeq + 1, maxSeq * 2); - report.merkleRoots[0].merkleRoot = "stale report 2"; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(report); - s_offRamp.reportCommit(abi.encode(report), s_latestEpochAndRound); + emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(maxSeq * 2 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); assertEq( tokenStartPrice, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value ); @@ -3271,26 +3287,37 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { function test_OnlyTokenPriceUpdates_Success() public { EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots }); + vm.expectEmit(); emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } function test_OnlyGasPriceUpdates_Success() public { EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots }); + vm.expectEmit(); emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { @@ -3298,14 +3325,19 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { uint224 tokenPrice1 = 4e18; uint224 tokenPrice2 = 5e18; EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), merkleRoots: roots }); + vm.expectEmit(); emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); roots = new EVM2EVMMultiOffRamp.MerkleRoot[](1); roots[0] = EVM2EVMMultiOffRamp.MerkleRoot({ @@ -3313,25 +3345,96 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: EVM2EVMMultiOffRamp.Interval(1, maxSeq), merkleRoot: "stale report" }); - report.priceUpdates = getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); - report.merkleRoots = roots; + commitReport.priceUpdates = getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); + commitReport.merkleRoots = roots; vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(report); - s_offRamp.reportCommit(abi.encode(report), s_latestEpochAndRound); + emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); assertEq( tokenPrice1, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value ); - assertEq(s_latestEpochAndRound, s_offRamp.getLatestPriceEpochAndRound()); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } + // Reverts - function test_Paused_Revert() public { - s_offRamp.pause(); - bytes memory report; - vm.expectRevert(EVM2EVMMultiOffRamp.PausedError.selector); - s_offRamp.reportCommit(report, ++s_latestEpochAndRound); + function test_UnauthorizedTransmitter_Revert() public { + EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = + [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_NoConfig_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + + EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_NoConfigWithOtherConfigPresent_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_WrongConfigWithoutSigners_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + + EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + vm.expectRevert(); + _commit(commitReport, s_latestSequenceNumber); } function test_Unhealthy_Revert() public { @@ -3343,10 +3446,11 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { merkleRoot: "Only a single root" }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_InvalidRootRevert() public { @@ -3356,10 +3460,11 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: EVM2EVMMultiOffRamp.Interval(1, 4), merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + vm.expectRevert(EVM2EVMMultiOffRamp.InvalidRoot.selector); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_InvalidInterval_Revert() public { @@ -3370,12 +3475,13 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: interval, merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + vm.expectRevert( abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval) ); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_InvalidIntervalMinLargerThanMax_Revert() public { @@ -3387,35 +3493,39 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: interval, merkleRoot: bytes32(0) }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); + vm.expectRevert( abi.encodeWithSelector(EVM2EVMMultiOffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval) ); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_ZeroEpochAndRound_Revert() public { EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots }); + vm.expectRevert(EVM2EVMMultiOffRamp.StaleCommitReport.selector); - s_offRamp.reportCommit(abi.encode(report), 0); + _commit(commitReport, 0); } function test_OnlyPriceUpdateStaleReport_Revert() public { EVM2EVMMultiOffRamp.MerkleRoot[] memory roots = new EVM2EVMMultiOffRamp.MerkleRoot[](0); - EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({ + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({ priceUpdates: getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots }); + vm.expectEmit(); emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); + vm.expectRevert(EVM2EVMMultiOffRamp.StaleCommitReport.selector); - s_offRamp.reportCommit(abi.encode(report), s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_SourceChainNotEnabled_Revert() public { @@ -3426,11 +3536,11 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { merkleRoot: "Only a single root" }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOffRamp.SourceChainNotEnabled.selector, 0)); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(commitReport, s_latestSequenceNumber); } function test_RootAlreadyCommitted_Revert() public { @@ -3440,129 +3550,18 @@ contract EVM2EVMMultiOffRamp_reportCommit is EVM2EVMMultiOffRampSetup { interval: EVM2EVMMultiOffRamp.Interval(1, 2), merkleRoot: "Only a single root" }); - EVM2EVMMultiOffRamp.CommitReport memory report = + EVM2EVMMultiOffRamp.CommitReport memory commitReport = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); - report.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(3, 3); + + _commit(commitReport, s_latestSequenceNumber); + commitReport.merkleRoots[0].interval = EVM2EVMMultiOffRamp.Interval(3, 3); + vm.expectRevert( abi.encodeWithSelector( EVM2EVMMultiOffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot ) ); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); - } -} - -contract EVM2EVMMultiOffRamp_commit is EVM2EVMMultiOffRampSetup { - uint64 internal s_maxInterval = 12; - - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - } - - function test_SingleReport_Success() public { - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [s_configDigestCommit, s_configDigestCommit, s_configDigestCommit]; - - // F = 1, need 2 signatures - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigestCommit, abi.encode(commitReport), 2); - - vm.expectEmit(); - emit EVM2EVMMultiOffRamp.CommitReportAccepted(commitReport); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, uint32(uint256(s_configDigestCommit) >> 8) - ); - - vm.startPrank(s_validTransmitters[0]); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - - assertEq(s_maxInterval + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(uint40(uint256(reportContext[1])), s_offRamp.getLatestPriceEpochAndRound()); - } - - // Reverts - - function test_UnauthorizedTransmitter_Revert() public { - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [s_configDigestCommit, s_configDigestCommit, s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigestCommit, abi.encode(commitReport), 2); - - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_NoConfig_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigestCommit, abi.encode(commitReport), 2); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_NoConfigWithOtherConfigPresent_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - uniqueReports: false, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigestCommit, abi.encode(commitReport), 2); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_WrongConfigWithoutSigners_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - EVM2EVMMultiOffRamp.CommitReport memory commitReport = _constructCommitReport(); - s_configDigestCommit = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - uniqueReports: false, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - bytes32[3] memory reportContext = [s_configDigestCommit, s_configDigestCommit, s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, s_configDigestCommit, abi.encode(commitReport), 2); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + _commit(commitReport, ++s_latestSequenceNumber); } function _constructCommitReport() internal view returns (EVM2EVMMultiOffRamp.CommitReport memory) { @@ -3614,7 +3613,7 @@ contract EVM2EVMMultiOffRamp_resetUnblessedRoots is EVM2EVMMultiOffRampSetup { EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(report, ++s_latestSequenceNumber); IRMN.TaggedRoot[] memory blessedTaggedRoots = new IRMN.TaggedRoot[](1); blessedTaggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: rootsToReset[1].merkleRoot}); @@ -3666,7 +3665,7 @@ contract EVM2EVMMultiOffRamp_verify is EVM2EVMMultiOffRampSetup { }); EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(report, ++s_latestSequenceNumber); bytes32[] memory proofs = new bytes32[](0); // We have not blessed this root, should return 0. uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); @@ -3684,7 +3683,7 @@ contract EVM2EVMMultiOffRamp_verify is EVM2EVMMultiOffRampSetup { }); EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(report, ++s_latestSequenceNumber); // Bless that root. IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: leaves[0]}); @@ -3707,7 +3706,7 @@ contract EVM2EVMMultiOffRamp_verify is EVM2EVMMultiOffRampSetup { EVM2EVMMultiOffRamp.CommitReport memory report = EVM2EVMMultiOffRamp.CommitReport({priceUpdates: getEmptyPriceUpdates(), merkleRoots: roots}); - s_offRamp.reportCommit(abi.encode(report), ++s_latestEpochAndRound); + _commit(report, ++s_latestSequenceNumber); // Bless that root. IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); @@ -3722,15 +3721,6 @@ contract EVM2EVMMultiOffRamp_verify is EVM2EVMMultiOffRampSetup { // Reverts - function test_Paused_Revert() public { - s_offRamp.pause(); - bytes32[] memory hashedLeaves = new bytes32[](0); - bytes32[] memory proofs = new bytes32[](0); - uint256 proofFlagBits = 0; - vm.expectRevert(EVM2EVMMultiOffRamp.PausedError.selector); - s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, proofFlagBits); - } - function test_TooManyLeaves_Revert() public { bytes32[] memory leaves = new bytes32[](258); bytes32[] memory proofs = new bytes32[](0); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index b8217808de..003671c6b1 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -57,7 +57,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba uint64 internal constant s_offchainConfigVersion = 3; uint8 internal constant s_F = 1; - uint40 internal s_latestEpochAndRound; + uint64 internal s_latestSequenceNumber; function setUp() public virtual override(TokenSetup, PriceRegistrySetup, MultiOCR3BaseSetup) { TokenSetup.setUp(); @@ -95,7 +95,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba ocrPluginType: uint8(Internal.OCRPluginType.Execution), configDigest: s_configDigestExec, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: false, signers: s_emptySigners, transmitters: s_validTransmitters @@ -104,7 +103,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba ocrPluginType: uint8(Internal.OCRPluginType.Commit), configDigest: s_configDigestCommit, F: s_F, - uniqueReports: false, isSignatureVerificationEnabled: true, signers: s_validSigners, transmitters: s_validTransmitters @@ -229,8 +227,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, router: router, priceRegistry: priceRegistry, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - maxDataBytes: MAX_DATA_SIZE, messageValidator: address(0), maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS @@ -411,8 +407,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba ) public pure { assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); assertEq(a.router, b.router); - assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); - assertEq(a.maxDataBytes, b.maxDataBytes); assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); assertEq(a.maxTokenTransferGas, b.maxTokenTransferGas); assertEq(a.messageValidator, b.messageValidator); @@ -484,4 +478,21 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, MultiOCR3Ba // Overwrite base mock rmn with real. s_realRMN = new RMN(RMN.Config({voters: voters, blessWeightThreshold: 1, curseWeightThreshold: 1})); } + + function _commit(EVM2EVMMultiOffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { + bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function _execute(Internal.ExecutionReportSingleChain[] memory reports) internal { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + vm.startPrank(s_validTransmitters[0]); + s_offRamp.execute(reportContext, abi.encode(reports)); + } } diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index 8c21d71aa0..7dc439b6ce 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -53,8 +53,6 @@ type EVM2EVMMultiOffRampDynamicConfig struct { PermissionLessExecutionThresholdSeconds uint32 MaxTokenTransferGas uint32 MaxPoolReleaseOrMintGas uint32 - MaxNumberOfTokensPerMsg uint16 - MaxDataBytes uint32 MessageValidator common.Address PriceRegistry common.Address } @@ -139,7 +137,6 @@ type MultiOCR3BaseConfigInfo struct { ConfigDigest [32]byte F uint8 N uint8 - UniqueReports bool IsSignatureVerificationEnabled bool } @@ -153,15 +150,14 @@ type MultiOCR3BaseOCRConfigArgs struct { ConfigDigest [32]byte OcrPluginType uint8 F uint8 - UniqueReports bool IsSignatureVerificationEnabled bool Signers []common.Address Transmitters []common.Address } var EVM2EVMMultiOffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PausedError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint40\",\"name\":\"oldEpochAndRound\",\"type\":\"uint40\"},{\"indexed\":false,\"internalType\":\"uint40\",\"name\":\"newEpochAndRound\",\"type\":\"uint40\"}],\"name\":\"LatestPriceEpochAndRoundSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceEpochAndRound\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"isUnpausedAndNotCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"uniqueReports\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint40\",\"name\":\"latestPriceEpochAndRound\",\"type\":\"uint40\"}],\"name\":\"setLatestPriceEpochAndRound\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"uniqueReports\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x610100604052600b805460ff60281b191690553480156200001f57600080fd5b5060405162007b1738038062007b17833981016040819052620000429162000608565b3380600081620000995760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000cc57620000cc8162000181565b5050466080525060208201516001600160a01b03161580620000f9575060408201516001600160a01b0316155b1562000118576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b0316600003620001445760405163c656089560e01b815260040160405180910390fd5b81516001600160401b031660a05260208201516001600160a01b0390811660c05260408301511660e05262000179816200022c565b505062000790565b336001600160a01b03821603620001db5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000090565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015620004dc5760008282815181106200025057620002506200077a565b60200260200101519050600081600001519050806001600160401b03166000036200028e5760405163c656089560e01b815260040160405180910390fd5b60608201516001600160a01b0316620002ba576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260076020526040902060018101546001600160a01b0316620003c0576200031c8284606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3620004e060201b60201c565b600282015560608301516001820180546001600160a01b039283166001600160a01b03199091161790556040808501518354610100600160481b03199190931669010000000000000000000216610100600160e81b031990921691909117610100178255516001600160401b03831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a16200042f565b606083015160018201546001600160a01b03908116911614158062000404575060408301518154690100000000000000000090046001600160a01b03908116911614155b156200042f5760405163c39a620560e01b81526001600160401b038316600482015260240162000090565b6020830151815490151560ff199091161781556040516001600160401b038316907fa73c588738263db34ef8c1942db8f99559bc6696f6a812d42e76bafb4c0e8d3090620004c5908490815460ff811615158252600881901c6001600160401b0316602083015260481c6001600160a01b0390811660408301526001830154166060820152600290910154608082015260a00190565b60405180910390a25050508060010190506200022f565b5050565b60a0805160408051602081018590526001600160401b0380881692820192909252911660608201526001600160a01b0384166080820152600091016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200057557620005756200053a565b60405290565b604051608081016001600160401b03811182821017156200057557620005756200053a565b604051601f8201601f191681016001600160401b0381118282101715620005cb57620005cb6200053a565b604052919050565b80516001600160401b0381168114620005eb57600080fd5b919050565b80516001600160a01b0381168114620005eb57600080fd5b6000808284036080808212156200061e57600080fd5b6060808312156200062e57600080fd5b6200063862000550565b92506200064586620005d3565b8352602062000656818801620005f0565b8185015260406200066a60408901620005f0565b604086015260608801519496506001600160401b03808611156200068d57600080fd5b858901955089601f870112620006a257600080fd5b855181811115620006b757620006b76200053a565b620006c7848260051b01620005a0565b818152848101925060079190911b87018401908b821115620006e857600080fd5b968401965b81881015620007685786888d031215620007075760008081fd5b620007116200057b565b6200071c89620005d3565b8152858901518015158114620007325760008081fd5b8187015262000743898601620005f0565b8582015262000754878a01620005f0565b8188015283529686019691840191620006ed565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516172f96200081e6000396000818161026c01528181610a0b0152612df2015260008181610230015281816109e4015281816110c30152818161180401528181611b2201526135d6015260008181610200015281816109c00152613fa6015260008181610c1201528181610c5e01528181611f5d0152611fa901526172f96000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80637f63b711116100f9578063ccd37ba311610097578063e9d68a8e11610071578063e9d68a8e146105f0578063f2fde38b14610718578063f52121a51461072b578063ff888fb11461073e57600080fd5b8063ccd37ba314610585578063d2a15d35146105ca578063d783efe7146105dd57600080fd5b80638b364334116100d35780638b364334146105175780638da5cb5b1461052a57806396c62bcc14610552578063c673e5841461056557600080fd5b80637f63b711146104ee5780638456cb591461050157806385572ffb1461050957600080fd5b8063311cd513116101665780635c975abb116101405780635c975abb146103805780635e36480c146103a05780637437ff9f146103c057806379ba5097146104e657600080fd5b8063311cd513146103525780633f4ba83a14610365578063542625af1461036d57600080fd5b8063181f5a7711610197578063181f5a77146102e357806329b980e41461032c5780632d04ab761461033f57600080fd5b806305a754ec146101be57806306285c69146101d357806310c374ed146102bf575b600080fd5b6101d16101cc3660046152db565b610751565b005b6102a9604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102b691906153a5565b60405180910390f35b600b5464ffffffffff165b60405167ffffffffffffffff90911681526020016102b6565b61031f6040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102b6919061543d565b6101d161033a366004615450565b610a6a565b6101d161034d36600461550f565b610ae9565b6101d16103603660046155c2565b610b76565b6101d1610ba9565b6101d161037b366004615bbf565b610c0f565b600b5465010000000000900460ff165b60405190151581526020016102b6565b6103b36103ae366004615cea565b610e3c565b6040516102b69190615d66565b6104d96040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915250604080516101008101825260045473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff74010000000000000000000000000000000000000000830481166020850152780100000000000000000000000000000000000000000000000083048116948401949094527c01000000000000000000000000000000000000000000000000000000009091048316606083015260055461ffff8116608084015262010000810490931660a08301526601000000000000909204821660c082015260065490911660e082015290565b6040516102b69190615e23565b6101d1610ed0565b6101d16104fc366004615e32565b610fcd565b6101d1610fe1565b6101d16101b9366004615f16565b6102ca610525366004615f51565b611049565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b6565b610390610560366004615f7f565b61105f565b610578610573366004615fad565b61114c565b6040516102b6919061601a565b6105bc61059336600461609c565b67ffffffffffffffff919091166000908152600a60209081526040808320938352929052205490565b6040519081526020016102b6565b6101d16105d83660046160c8565b6112dd565b6101d16105eb3660046161a5565b611397565b6106ae6105fe366004615f7f565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525067ffffffffffffffff908116600090815260076020908152604091829020825160a081018452815460ff81161515825261010081049095169281019290925273ffffffffffffffffffffffffffffffffffffffff69010000000000000000009094048416928201929092526001820154909216606083015260020154608082015290565b6040516102b69190600060a08201905082511515825267ffffffffffffffff6020840151166020830152604083015173ffffffffffffffffffffffffffffffffffffffff808216604085015280606086015116606085015250506080830151608083015292915050565b6101d1610726366004616305565b6113d9565b6101d1610739366004616322565b6113ea565b61039061074c366004616386565b6117a1565b61075961186f565b60e081015173ffffffffffffffffffffffffffffffffffffffff166107aa576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff166107f8576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085015160408087015160608089015163ffffffff9081167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9382167801000000000000000000000000000000000000000000000000029390931677ffffffffffffffffffffffffffffffffffffffffffffffff95821674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090981673ffffffffffffffffffffffffffffffffffffffff9a8b16179790971794909416959095171790945560808601516005805460a089015160c08a015189166601000000000000027fffffffffffff0000000000000000000000000000000000000000ffffffffffff9190951662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000090921661ffff90941693909317179190911691909117905560e0850151600680549186167fffffffffffffffffffffffff0000000000000000000000000000000000000000929092169190911790558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008416908201527f000000000000000000000000000000000000000000000000000000000000000090921682820152517ff778ca28f5b9f37b5d23ffa5357592348ea60ec4e42b1dce5c857a5a65b276f791610a5f91849061639f565b60405180910390a150565b610a7261186f565b600b805464ffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000083168117909355604080519190921680825260208201939093527ff0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf565456444910160405180910390a15050565b610af8878760208b01356118f2565b610b6c600089898989898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a9250611e19915050565b5050505050505050565b610b80828261226b565b604080516000808252602082019092529050610ba3600185858585866000611e19565b50505050565b610bb161186f565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b467f000000000000000000000000000000000000000000000000000000000000000014610c9f576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff461660248201526044015b60405180910390fd5b815181518114610cdb576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610e2c576000848281518110610cfa57610cfa6163f5565b60200260200101519050600081602001515190506000858481518110610d2257610d226163f5565b6020026020010151905080518214610d66576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610e1d576000828281518110610d8557610d856163f5565b6020026020010151905080600014158015610dc0575084602001518281518110610db157610db16163f5565b60200260200101516080015181105b15610e145784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610c96565b50600101610d69565b50505050806001019050610cde565b50610e3783836122a7565b505050565b6000610e4a60016004616453565b6002610e57608085616495565b67ffffffffffffffff16610e6b91906164bc565b67ffffffffffffffff8516600090815260096020526040812090610e906080876164d3565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610ec757610ec7615d23565b90505b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610c96565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610fd561186f565b610fde81612357565b50565b610fe961186f565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffff16650100000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610c05565b60008061105684846126f5565b50949350505050565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561110a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112e91906164fa565b158015610eca5750600b5465010000000000900460ff161592915050565b6111976040805161010081019091526000606082018181526080830182905260a0830182905260c0830182905260e08301919091528190815260200160608152602001606081525090565b60ff8083166000908152600260208181526040928390208351610100808201865282546060830190815260018401548089166080850152918204881660a08401526201000082048816151560c08401526301000000909104909616151560e08201529485529182018054845181840281018401909552808552929385830193909283018282801561125e57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611233575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156112cd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116112a2575b5050505050815250509050919050565b6112e561186f565b60005b81811015610e37576000838383818110611304576113046163f5565b90506040020180360381019061131a9190616517565b905061132981602001516117a1565b61138e57805167ffffffffffffffff166000908152600a602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016112e8565b61139f61186f565b60005b81518110156113d5576113cd8282815181106113c0576113c06163f5565b602002602001015161282d565b6001016113a2565b5050565b6113e161186f565b610fde81612c65565b333014611423576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611460565b60408051808201909152600080825260208201528152602001906001900390816114395790505b5061014084015151909150156114fb576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff1660808201526114f891908060a0810160408051601f19818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612d5a565b90505b600061150784836132a2565b6005549091506601000000000000900473ffffffffffffffffffffffffffffffffffffffff168015611618576040517fa219f6e500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063a219f6e59061158590859060040161660c565b600060405180830381600087803b15801561159f57600080fd5b505af19250505080156115b0575060015b611618573d8080156115de576040519150601f19603f3d011682016040523d82523d6000602084013e6115e3565b606091505b50806040517f09c25325000000000000000000000000000000000000000000000000000000008152600401610c96919061543d565b6101208501515115801561162e57506080850151155b806116525750604085015173ffffffffffffffffffffffffffffffffffffffff163b155b8061169f5750604085015161169d9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb00000000000000000000000000000000000000000000000000000000613352565b155b156116ab575050505050565b60048054608087015160408089015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600094859473ffffffffffffffffffffffffffffffffffffffff1693633cf9798393611713938a936113889392910161661f565b6000604051808303816000875af1158015611732573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261175a91908101906166ad565b50915091508161179857806040517f0a8d6e8c000000000000000000000000000000000000000000000000000000008152600401610c96919061543d565b50505050505050565b6040805180820182523081526020810183815291517f4d616771000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa15801561184b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eca91906164fa565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c96565b565b600b5465010000000000900460ff1615611938576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061194683850185616894565b8051515190915015158061195f57508051602001515115155b15611a8857600b5464ffffffffff80841691161015611a4957600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000001664ffffffffff841617905560065481516040517f3937306f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90921691633937306f916119ff91600401616af3565b600060405180830381600087803b158015611a1957600080fd5b505af1158015611a2d573d6000803e3d6000fd5b50505050806020015151600003611a445750505050565b611a88565b806020015151600003611a88576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b816020015151811015611ddb57600082602001518281518110611ab057611ab06163f5565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b1660048201529192509073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015611b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8d91906164fa565b15611bd0576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610c96565b67ffffffffffffffff81166000908152600760205260409020805460ff16611c30576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610c96565b6020830151518154610100900467ffffffffffffffff9081169116141580611c6f575060208084015190810151905167ffffffffffffffff9182169116115b15611caf57825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610c96929190600401616b06565b6040830151611cea576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff166000908152600a6020908152604080832081870151845290915290205415611d6357825160408085015190517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90921660048301526024820152604401610c96565b6020808401510151611d76906001616b3b565b81547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff92831602179091558251166000908152600a602090815260408083209481015183529390529190912042905550600101611a8b565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051611e0b9190616b63565b60405180910390a150505050565b60ff8781166000908152600260209081526040808320815160a08101835281548152600190910154808616938201939093526101008304851691810191909152620100008204841615156060820152630100000090910490921615156080830152873590611e888760a4616c00565b9050826080015115611ed0578451611ea19060206164bc565b8651611eae9060206164bc565b611eb99060a0616c00565b611ec39190616c00565b611ecd9082616c00565b90505b368114611f12576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610c96565b5081518114611f5a5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610c96565b467f000000000000000000000000000000000000000000000000000000000000000014611fdb576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610c96565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561202957612029615d23565b600281111561203a5761203a615d23565b905250905060028160200151600281111561205757612057615d23565b1480156120b85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110612093576120936163f5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6120ee576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081608001511561221657600082606001511561213a5760028360200151846040015161211b9190616c13565b6121259190616c2c565b612130906001616c13565b60ff169050612150565b602083015161214a906001616c13565b60ff1690505b8086511461218a576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84518651146121c5576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600087876040516121d8929190616c4e565b6040519081900381206121ef918b90602001616c5e565b6040516020818303038152906040528051906020012090506122148a8288888861336e565b505b6040805182815260208a81013560081c63ffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b6113d561227a82840184616c72565b60408051600080825260208201909252906122a5565b60608152602001906001900390816122905790505b505b81516000036122e1576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561235057612348858281518110612316576123166163f5565b60200260200101518461234257858381518110612335576123356163f5565b6020026020010151613588565b83613588565b6001016122f8565b5050505050565b60005b81518110156113d5576000828281518110612377576123776163f5565b602002602001015190506000816000015190508067ffffffffffffffff166000036123ce576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606082015173ffffffffffffffffffffffffffffffffffffffff1661241f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600760205260409020600181015473ffffffffffffffffffffffffffffffffffffffff1661257d576124868284606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3613fa0565b6002820155606083015160018201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560408085015183547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff91909316690100000000000000000002167fffffff00000000000000000000000000000000000000000000000000000000ff909216919091176101001782555167ffffffffffffffff831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161261d565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff90811691161415806125da5750604083015181546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff908116911614155b1561261d576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610c96565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fa73c588738263db34ef8c1942db8f99559bc6696f6a812d42e76bafb4c0e8d30906126df908490815460ff811615158252600881901c67ffffffffffffffff16602083015260481c73ffffffffffffffffffffffffffffffffffffffff90811660408301526001830154166060820152600290910154608082015260a00190565b60405180910390a250505080600101905061235a565b67ffffffffffffffff808316600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054909182911680820361281f5767ffffffffffffffff85166000908152600760205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff16801561281d576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa1580156127ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128109190616ca7565b6001935093505050612826565b505b9150600090505b9250929050565b806040015160ff166000036128715760006040517f367f56a2000000000000000000000000000000000000000000000000000000008152600401610c969190616cc4565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003612911576060840151600182018054608087015115156301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff9315156201000002939093167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff9091161791909117905561298b565b6060840151600182015460ff6201000090910416151590151514158061294f57506080840151600182015460ff630100000090910416151590151514155b1561298b576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610c96565b60c08401518051601f60ff821611156129d35760016040517f367f56a2000000000000000000000000000000000000000000000000000000008152600401610c969190616cc4565b612a468585600301805480602002602001604051908101604052809291908181526020018280548015612a3c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612a11575b5050505050614030565b856080015115612bb457612ac18585600201805480602002602001604051908101604052809291908181526020018280548015612a3c5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612a11575050505050614030565b60a08601518051612adb9060028701906020840190615090565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612b545760026040517f367f56a2000000000000000000000000000000000000000000000000000000008152600401610c969190616cc4565b6040880151612b64906003616cde565b60ff168160ff1611612ba55760036040517f367f56a2000000000000000000000000000000000000000000000000000000008152600401610c969190616cc4565b612bb1878360016140c3565b50505b612bc0858360026140c3565b8151612bd59060038601906020850190615090565b506040868101516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055875180865560c089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793612c4c938a939260028b01929190616cfa565b60405180910390a1612c5d856142be565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612ce4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c96565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015611056576000848281518110612d7b57612d7b6163f5565b6020026020010151806020019051810190612d969190616dc6565b90506000612da782602001516142f1565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5d9190616e7b565b905073ffffffffffffffffffffffffffffffffffffffff81161580612ebf5750612ebd73ffffffffffffffffffffffffffffffffffffffff82167faff2afbf00000000000000000000000000000000000000000000000000000000613352565b155b15612f0e576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610c96565b60008061307b633907753760e01b6040518061010001604052808d6000015181526020018d6020015167ffffffffffffffff1681526020018d6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018e8a81518110612f7857612f786163f5565b60200260200101516020015181526020018773ffffffffffffffffffffffffffffffffffffffff16815260200188600001518152602001886040015181526020018b8a81518110612fcb57612fcb6163f5565b6020026020010151815250604051602401612fe69190616e98565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600454859063ffffffff7c010000000000000000000000000000000000000000000000000000000090910416611388608461434c565b5091509150816130b957806040517fe1cd5509000000000000000000000000000000000000000000000000000000008152600401610c96919061543d565b80516020146131015780516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610c96565b6000818060200190518101906131179190616f7f565b60408c810151815173ffffffffffffffffffffffffffffffffffffffff909116602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526004549192506131d69187907801000000000000000000000000000000000000000000000000900463ffffffff16611388608461434c565b5090935091508261321557816040517fe1cd5509000000000000000000000000000000000000000000000000000000008152600401610c96919061543d565b84888881518110613228576132286163f5565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080888881518110613279576132796163f5565b60200260200101516020018181525050505050505050806001019050612d5e565b949350505050565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001613327919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b600061335d83614472565b8015610ec75750610ec783836144d6565b613376615116565b835160005b81811015610b6c57600060018886846020811061339a5761339a6163f5565b6133a791901a601b616c13565b8985815181106133b9576133b96163f5565b60200260200101518986815181106133d3576133d36163f5565b602002602001015160405160008152602001604052604051613411949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015613433573d6000803e3d6000fd5b505060408051601f1981015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156134a1576134a1615d23565b60028111156134b2576134b2615d23565b90525090506001816020015160028111156134cf576134cf615d23565b14613506576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061351d5761351d6163f5565b602002015115613559576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110613574576135746163f5565b91151560209092020152505060010161337b565b81516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015613632573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365691906164fa565b15613699576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610c96565b60208301515160008190036136d9576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360400151518114613717576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600760205260409020805460ff16613777576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610c96565b60008267ffffffffffffffff8111156137925761379261514a565b6040519080825280602002602001820160405280156137bb578160200160208202803683370190505b50905060005b83811015613880576000876020015182815181106137e1576137e16163f5565b602002602001015190506137f98185600201546145a5565b83838151811061380b5761380b6163f5565b60200260200101818152505080610180015183838151811061382f5761382f6163f5565b602002602001015114613877578061018001516040517f345039be000000000000000000000000000000000000000000000000000000008152600401610c9691815260200190565b506001016137c1565b506000613897858389606001518a6080015161470e565b9050806000036138df576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610c96565b8551151560005b85811015613f9557600089602001518281518110613906576139066163f5565b602002602001015190506000613920898360600151610e3c565b9050600281600381111561393657613936615d23565b0361398c5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050613f8d565b60008160038111156139a0576139a0615d23565b14806139bd575060038160038111156139bb576139bb615d23565b145b613a0d5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610c96565b8315613aee5760045460009074010000000000000000000000000000000000000000900463ffffffff16613a418742616453565b1190508080613a6157506003826003811115613a5f57613a5f615d23565b145b613aa3576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610c96565b8a8481518110613ab557613ab56163f5565b6020026020010151600014613ae8578a8481518110613ad657613ad66163f5565b60200260200101518360800181815250505b50613b53565b6000816003811115613b0257613b02615d23565b14613b535760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610c96565b600080613b648b85602001516126f5565b915091508015613c845760c084015167ffffffffffffffff16613b88836001616b3b565b67ffffffffffffffff1614613c185760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92613c07928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050613f8d565b67ffffffffffffffff8b811660009081526008602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115613c9857613c98615d23565b03613d365760c084015167ffffffffffffffff16613cb7836001616b3b565b67ffffffffffffffff1614613d365760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992613c07928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110613d4e57613d4e6163f5565b60200260200101519050613d7c8561018001518d8760600151886101400151518961012001515186516147ab565b613d8c8c866060015160016148b3565b600080613d998784614991565b91509150613dac8e8860600151846148b3565b888015613dca57506003826003811115613dc857613dc8615d23565b145b8015613de857506000866003811115613de557613de5615d23565b14155b15613e2857866101800151816040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610c96929190616f98565b6003826003811115613e3c57613e3c615d23565b14158015613e5c57506002826003811115613e5957613e59615d23565b14155b15613e9d578d8760600151836040517f926c5a3e000000000000000000000000000000000000000000000000000000008152600401610c9693929190616fb1565b6000866003811115613eb157613eb1615d23565b03613f2c5767ffffffffffffffff808f1660009081526008602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190613f0483616fd7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051613f7d929190616ffe565b60405180910390a4505050505050505b6001016138e6565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001614010949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60005b8151811015610e375760ff831660009081526003602052604081208351909190849084908110614065576140656163f5565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101614033565b60005b82518160ff161015610ba3576000838260ff16815181106140e9576140e96163f5565b602002602001015190506000600281111561410657614106615d23565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561415257614152615d23565b1461418c5760046040517f367f56a2000000000000000000000000000000000000000000000000000000008152600401610c969190616cc4565b73ffffffffffffffffffffffffffffffffffffffff81166141d9576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156141ff576141ff615d23565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156142a4576142a4615d23565b021790555090505050806142b79061701e565b90506140c6565b60ff8116610fde57600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000016905550565b6000815160201461433057816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610c96919061543d565b610eca828060200190518101906143479190616f7f565b614cb5565b6000606060008361ffff1667ffffffffffffffff81111561436f5761436f61514a565b6040519080825280601f01601f191660200182016040528015614399576020820181803683370190505b509150863b6143cc577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156143ff577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710614438577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561445b5750835b808352806000602085013e50955095509592505050565b600061449e827f01ffc9a7000000000000000000000000000000000000000000000000000000006144d6565b8015610eca57506144cf827fffffffff000000000000000000000000000000000000000000000000000000006144d6565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561458e575060208210155b801561459a5750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b610100015160405160200161464898979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001614681919061703d565b604051602081830303815290604052805190602001208761016001516040516020016146ad91906170ff565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b600b5460009065010000000000900460ff1615614757576040517feced32bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000614764858585614d2f565b905061476f816117a1565b61477d57600091505061329a565b67ffffffffffffffff86166000908152600a6020908152604080832093835292905220549050949350505050565b60055461ffff168311156147ff576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610c96565b80831461484c576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610c96565b60055462010000900463ffffffff16821115612c5d576005546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890526201000090910463ffffffff16602482015260448101839052606401610c96565b600060026148c2608085616495565b67ffffffffffffffff166148d691906164bc565b67ffffffffffffffff8516600090815260096020526040812091925090816148ff6080876164d3565b67ffffffffffffffff16815260208101919091526040016000205490508161492960016004616453565b901b19168183600381111561494057614940615d23565b67ffffffffffffffff871660009081526009602052604081209190921b9290921791829161496f6080886164d3565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a5906149d59087908790600401617112565b600060405180830381600087803b1580156149ef57600080fd5b505af1925050508015614a00575060015b614c9a573d808015614a2e576040519150601f19603f3d011682016040523d82523d6000602084013e614a33565b606091505b506000614a3f8261729c565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082161480614ad257507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b80614b1e57507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b80614b6a57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b80614bb657507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b80614c0257507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b80614c4e57507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b15614c5f5750600392509050612826565b856101800151826040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610c96929190616f98565b50506040805160208101909152600081526002909250929050565b600073ffffffffffffffffffffffffffffffffffffffff821180614cda575061040082105b15614d2b5760408051602081018490520160408051601f19818403018152908290527f8d666f60000000000000000000000000000000000000000000000000000000008252610c969160040161543d565b5090565b8251825160009190818303614d70576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590614d8457506101018111155b614dba576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82820101610100811115614e1b576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600003614e485786600081518110614e3657614e366163f5565b60200260200101519350505050614029565b60008167ffffffffffffffff811115614e6357614e6361514a565b604051908082528060200260200182016040528015614e8c578160200160208202803683370190505b50905060008080805b85811015614fcf5760006001821b8b811603614ef05788851015614ed9578c5160018601958e918110614eca57614eca6163f5565b60200260200101519050614f12565b8551600185019487918110614eca57614eca6163f5565b8b5160018401938d918110614f0757614f076163f5565b602002602001015190505b600089861015614f42578d5160018701968f918110614f3357614f336163f5565b60200260200101519050614f64565b8651600186019588918110614f5957614f596163f5565b602002602001015190505b82851115614f9e576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fa8828261504f565b878481518110614fba57614fba6163f5565b60209081029190910101525050600101614e95565b506001850382148015614fe157508683145b8015614fec57508581145b615022576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001860381518110615037576150376163f5565b60200260200101519750505050505050509392505050565b600081831061506757615062828461506d565b610ec7565b610ec783835b6040805160016020820152908101839052606081018290526000906080016146f0565b82805482825590600052602060002090810192821561510a579160200282015b8281111561510a57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906150b0565b50614d2b929150615135565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115614d2b5760008155600101615136565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561519c5761519c61514a565b60405290565b6040516101a0810167ffffffffffffffff8111828210171561519c5761519c61514a565b60405160a0810167ffffffffffffffff8111828210171561519c5761519c61514a565b6040516080810167ffffffffffffffff8111828210171561519c5761519c61514a565b60405160e0810167ffffffffffffffff8111828210171561519c5761519c61514a565b6040516060810167ffffffffffffffff8111828210171561519c5761519c61514a565b604051601f8201601f1916810167ffffffffffffffff8111828210171561527b5761527b61514a565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610fde57600080fd5b80356152b081615283565b919050565b803563ffffffff811681146152b057600080fd5b803561ffff811681146152b057600080fd5b60006101008083850312156152ef57600080fd5b6040519081019067ffffffffffffffff821181831017156153125761531261514a565b816040528335915061532382615283565b818152615332602085016152b5565b6020820152615343604085016152b5565b6040820152615354606085016152b5565b6060820152615365608085016152c9565b608082015261537660a085016152b5565b60a082015261538760c085016152a5565b60c082015261539860e085016152a5565b60e0820152949350505050565b60608101610eca8284805167ffffffffffffffff16825260208082015173ffffffffffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60005b838110156154085781810151838201526020016153f0565b50506000910152565b600081518084526154298160208601602086016153ed565b601f01601f19169290920160200192915050565b602081526000610ec76020830184615411565b60006020828403121561546257600080fd5b813564ffffffffff8116811461402957600080fd5b8060608101831015610eca57600080fd5b60008083601f84011261549a57600080fd5b50813567ffffffffffffffff8111156154b257600080fd5b60208301915083602082850101111561282657600080fd5b60008083601f8401126154dc57600080fd5b50813567ffffffffffffffff8111156154f457600080fd5b6020830191508360208260051b850101111561282657600080fd5b60008060008060008060008060e0898b03121561552b57600080fd5b6155358a8a615477565b9750606089013567ffffffffffffffff8082111561555257600080fd5b61555e8c838d01615488565b909950975060808b013591508082111561557757600080fd5b6155838c838d016154ca565b909750955060a08b013591508082111561559c57600080fd5b506155a98b828c016154ca565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156155d757600080fd5b6155e18585615477565b9250606084013567ffffffffffffffff8111156155fd57600080fd5b61560986828701615488565b9497909650939450505050565b600067ffffffffffffffff8211156156305761563061514a565b5060051b60200190565b67ffffffffffffffff81168114610fde57600080fd5b80356152b08161563a565b8015158114610fde57600080fd5b80356152b08161565b565b600067ffffffffffffffff82111561568e5761568e61514a565b50601f01601f191660200190565b600082601f8301126156ad57600080fd5b81356156c06156bb82615674565b615252565b8181528460208386010111156156d557600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261570357600080fd5b813560206157136156bb83615616565b82815260069290921b8401810191818101908684111561573257600080fd5b8286015b8481101561577a576040818903121561574f5760008081fd5b615757615179565b813561576281615283565b81528185013585820152835291830191604001615736565b509695505050505050565b600082601f83011261579657600080fd5b813560206157a66156bb83615616565b82815260059290921b840181019181810190868411156157c557600080fd5b8286015b8481101561577a57803567ffffffffffffffff8111156157e95760008081fd5b6157f78986838b010161569c565b8452509183019183016157c9565b60006101a0828403121561581857600080fd5b6158206151a2565b905061582b82615650565b8152615839602083016152a5565b602082015261584a604083016152a5565b604082015261585b60608301615650565b60608201526080820135608082015261587660a08301615669565b60a082015261588760c08301615650565b60c082015261589860e083016152a5565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156158c557600080fd5b6158d18683870161569c565b838501526101409250828501359150808211156158ed57600080fd5b6158f9868387016156f2565b8385015261016092508285013591508082111561591557600080fd5b5061592285828601615785565b82840152505061018080830135818301525092915050565b600082601f83011261594b57600080fd5b8135602061595b6156bb83615616565b82815260059290921b8401810191818101908684111561597a57600080fd5b8286015b8481101561577a57803567ffffffffffffffff81111561599e5760008081fd5b6159ac8986838b0101615805565b84525091830191830161597e565b600082601f8301126159cb57600080fd5b813560206159db6156bb83615616565b82815260059290921b840181019181810190868411156159fa57600080fd5b8286015b8481101561577a57803567ffffffffffffffff811115615a1e5760008081fd5b615a2c8986838b0101615785565b8452509183019183016159fe565b600082601f830112615a4b57600080fd5b81356020615a5b6156bb83615616565b8083825260208201915060208460051b870101935086841115615a7d57600080fd5b602086015b8481101561577a5780358352918301918301615a82565b600082601f830112615aaa57600080fd5b81356020615aba6156bb83615616565b82815260059290921b84018101918181019086841115615ad957600080fd5b8286015b8481101561577a57803567ffffffffffffffff80821115615afe5760008081fd5b818901915060a080601f19848d03011215615b195760008081fd5b615b216151c6565b615b2c888501615650565b815260408085013584811115615b425760008081fd5b615b508e8b8389010161593a565b8a8401525060608086013585811115615b695760008081fd5b615b778f8c838a01016159ba565b8385015250608091508186013585811115615b925760008081fd5b615ba08f8c838a0101615a3a565b9184019190915250919093013590830152508352918301918301615add565b6000806040808486031215615bd357600080fd5b833567ffffffffffffffff80821115615beb57600080fd5b615bf787838801615a99565b9450602091508186013581811115615c0e57600080fd5b8601601f81018813615c1f57600080fd5b8035615c2d6156bb82615616565b81815260059190911b8201840190848101908a831115615c4c57600080fd5b8584015b83811015615cd857803586811115615c685760008081fd5b8501603f81018d13615c7a5760008081fd5b87810135615c8a6156bb82615616565b81815260059190911b82018a0190898101908f831115615caa5760008081fd5b928b01925b82841015615cc85783358252928a0192908a0190615caf565b8652505050918601918601615c50565b50809750505050505050509250929050565b60008060408385031215615cfd57600080fd5b8235615d088161563a565b91506020830135615d188161563a565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110615d6257615d62615d23565b9052565b60208101610eca8284615d52565b73ffffffffffffffffffffffffffffffffffffffff8151168252602081015163ffffffff808216602085015280604084015116604085015280606084015116606085015261ffff60808401511660808501528060a08401511660a0850152505060c0810151615dfb60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e0810151610e3760e084018273ffffffffffffffffffffffffffffffffffffffff169052565b6101008101610eca8284615d74565b60006020808385031215615e4557600080fd5b823567ffffffffffffffff811115615e5c57600080fd5b8301601f81018513615e6d57600080fd5b8035615e7b6156bb82615616565b81815260079190911b82018301908381019087831115615e9a57600080fd5b928401925b8284101561459a5760808489031215615eb85760008081fd5b615ec06151e9565b8435615ecb8161563a565b815284860135615eda8161565b565b81870152604085810135615eed81615283565b90820152606085810135615f0081615283565b9082015282526080939093019290840190615e9f565b600060208284031215615f2857600080fd5b813567ffffffffffffffff811115615f3f57600080fd5b820160a0818503121561402957600080fd5b60008060408385031215615f6457600080fd5b8235615f6f8161563a565b91506020830135615d1881615283565b600060208284031215615f9157600080fd5b81356140298161563a565b803560ff811681146152b057600080fd5b600060208284031215615fbf57600080fd5b610ec782615f9c565b60008151808452602080850194506020840160005b8381101561600f57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615fdd565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff60408201511660608401526060810151151560808401526080810151151560a084015250602083015160e060c0840152616076610100840182615fc8565b90506040840151601f198483030160e08501526160938282615fc8565b95945050505050565b600080604083850312156160af57600080fd5b82356160ba8161563a565b946020939093013593505050565b600080602083850312156160db57600080fd5b823567ffffffffffffffff808211156160f357600080fd5b818501915085601f83011261610757600080fd5b81358181111561611657600080fd5b8660208260061b850101111561612b57600080fd5b60209290920196919550909350505050565b600082601f83011261614e57600080fd5b8135602061615e6156bb83615616565b8083825260208201915060208460051b87010193508684111561618057600080fd5b602086015b8481101561577a57803561619881615283565b8352918301918301616185565b600060208083850312156161b857600080fd5b823567ffffffffffffffff808211156161d057600080fd5b818501915085601f8301126161e457600080fd5b81356161f26156bb82615616565b81815260059190911b8301840190848101908883111561621157600080fd5b8585015b838110156162f85780358581111561622c57600080fd5b860160e0818c03601f190112156162435760008081fd5b61624b61520c565b888201358152604061625e818401615f9c565b8a830152606061626f818501615f9c565b8284015260809150616282828501615669565b9083015260a0616293848201615669565b8284015260c0915081840135898111156162ad5760008081fd5b6162bb8f8d8388010161613d565b82850152505060e0830135888111156162d45760008081fd5b6162e28e8c8387010161613d565b9183019190915250845250918601918601616215565b5098975050505050505050565b60006020828403121561631757600080fd5b813561402981615283565b6000806040838503121561633557600080fd5b823567ffffffffffffffff8082111561634d57600080fd5b61635986838701615805565b9350602085013591508082111561636f57600080fd5b5061637c85828601615785565b9150509250929050565b60006020828403121561639857600080fd5b5035919050565b61016081016163e88285805167ffffffffffffffff16825260208082015173ffffffffffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6140296060830184615d74565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610eca57610eca616424565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff808416806164b0576164b0616466565b92169190910692915050565b8082028115828204841417610eca57610eca616424565b600067ffffffffffffffff808416806164ee576164ee616466565b92169190910492915050565b60006020828403121561650c57600080fd5b81516140298161565b565b60006040828403121561652957600080fd5b616531615179565b823561653c8161563a565b81526020928301359281019290925250919050565b60008151808452602080850194506020840160005b8381101561600f578151805173ffffffffffffffffffffffffffffffffffffffff1688526020908101519088015260408701965090820190600101616566565b8051825267ffffffffffffffff60208201511660208301526000604082015160a060408501526165d960a0850182615411565b9050606083015184820360608601526165f28282615411565b915050608083015184820360808601526160938282616551565b602081526000610ec760208301846165a6565b60808152600061663260808301876165a6565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f83011261667957600080fd5b81516166876156bb82615674565b81815284602083860101111561669c57600080fd5b61329a8260208301602087016153ed565b6000806000606084860312156166c257600080fd5b83516166cd8161565b565b602085015190935067ffffffffffffffff8111156166ea57600080fd5b6166f686828701616668565b925050604084015190509250925092565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146152b057600080fd5b600082601f83011261674457600080fd5b813560206167546156bb83615616565b82815260069290921b8401810191818101908684111561677357600080fd5b8286015b8481101561577a57604081890312156167905760008081fd5b616798615179565b81356167a38161563a565b81526167b0828601616707565b81860152835291830191604001616777565b600082601f8301126167d357600080fd5b813560206167e36156bb83615616565b82815260079290921b8401810191818101908684111561680257600080fd5b8286015b8481101561577a5780880360808112156168205760008081fd5b61682861522f565b82356168338161563a565b81526040601f1983018113156168495760008081fd5b616851615179565b9250868401356168608161563a565b83528381013561686f8161563a565b8388015281870192909252606083013591810191909152835291830191608001616806565b600060208083850312156168a757600080fd5b823567ffffffffffffffff808211156168bf57600080fd5b818501915060408083880312156168d557600080fd5b6168dd615179565b8335838111156168ec57600080fd5b84016040818a0312156168fe57600080fd5b616906615179565b81358581111561691557600080fd5b8201601f81018b1361692657600080fd5b80356169346156bb82615616565b81815260069190911b8201890190898101908d83111561695357600080fd5b928a01925b828410156169a35787848f0312156169705760008081fd5b616978615179565b843561698381615283565b8152616990858d01616707565b818d0152825292870192908a0190616958565b8452505050818701359350848411156169bb57600080fd5b6169c78a858401616733565b81880152825250838501359150828211156169e157600080fd5b6169ed888386016167c2565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b81811015616a78578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101616a1f565b50508583015187820388850152805180835290840192506000918401905b80831015616ae7578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685830152928401926001929092019190850190616a96565b50979650505050505050565b602081526000610ec760208301846169ff565b67ffffffffffffffff83168152606081016140296020830184805167ffffffffffffffff908116835260209182015116910152565b67ffffffffffffffff818116838216019080821115616b5c57616b5c616424565b5092915050565b600060208083526060845160408084870152616b8260608701836169ff565b87850151878203601f19016040890152805180835290860193506000918601905b808310156162f857845167ffffffffffffffff815116835287810151616be289850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190616ba3565b80820180821115610eca57610eca616424565b60ff8181168382160190811115610eca57610eca616424565b600060ff831680616c3f57616c3f616466565b8060ff84160491505092915050565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215616c8457600080fd5b813567ffffffffffffffff811115616c9b57600080fd5b61329a84828501615a99565b600060208284031215616cb957600080fd5b81516140298161563a565b6020810160058310616cd857616cd8615d23565b91905290565b60ff8181168382160290811690818114616b5c57616b5c616424565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015616d5f57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201616d2d565b50508481036060860152865180825290820192508187019060005b81811015616dac57825173ffffffffffffffffffffffffffffffffffffffff1685529383019391830191600101616d7a565b50505060ff851660808501525090505b9695505050505050565b600060208284031215616dd857600080fd5b815167ffffffffffffffff80821115616df057600080fd5b9083019060608286031215616e0457600080fd5b616e0c61522f565b825182811115616e1b57600080fd5b616e2787828601616668565b825250602083015182811115616e3c57600080fd5b616e4887828601616668565b602083015250604083015182811115616e6057600080fd5b616e6c87828601616668565b60408301525095945050505050565b600060208284031215616e8d57600080fd5b815161402981615283565b6020815260008251610100806020850152616eb7610120850183615411565b91506020850151616ed4604086018267ffffffffffffffff169052565b50604085015173ffffffffffffffffffffffffffffffffffffffff8116606086015250606085015160808501526080850151616f2860a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a0850151601f19808685030160c0870152616f458483615411565b935060c08701519150808685030160e0870152616f628483615411565b935060e0870151915080868503018387015250616dbc8382615411565b600060208284031215616f9157600080fd5b5051919050565b82815260406020820152600061329a6040830184615411565b67ffffffffffffffff8481168252831660208201526060810161329a6040830184615d52565b600067ffffffffffffffff808316818103616ff457616ff4616424565b6001019392505050565b6170088184615d52565b60406020820152600061329a6040830184615411565b600060ff821660ff810361703457617034616424565b60010192915050565b6020808252825182820181905260009190848201906040850190845b81811015617099578351805173ffffffffffffffffffffffffffffffffffffffff1684526020908101519084015260408301938501939250600101617059565b50909695505050505050565b60008282518085526020808601955060208260051b8401016020860160005b848110156170f257601f198684030189526170e0838351615411565b988401989250908301906001016170c4565b5090979650505050505050565b602081526000610ec760208301846170a5565b6040815261712d60408201845167ffffffffffffffff169052565b60006020840151617156606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c08401516101006171c48185018367ffffffffffffffff169052565b60e086015191506101206171ef8186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a0610160818187015261721f6101e0870185615411565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc061018081888703018189015261725e8686616551565b9550828a0151945081888703018489015261727986866170a5565b9550808a01516101c08901525050505050828103602084015261609381856170a5565b6000815160208301517fffffffff00000000000000000000000000000000000000000000000000000000808216935060048310156172e45780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"oldSequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newSequenceNumber\",\"type\":\"uint64\"}],\"name\":\"LatestPriceSequenceNumberSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"latestPriceSequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setLatestPriceSequenceNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620067e1380380620067e1833981016040819052620000359162000648565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001c1565b5050466080525060208201516001600160a01b03161580620000ec575060408201516001600160a01b0316155b156200010b576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160401b0316600003620001375760405163c656089560e01b815260040160405180910390fd5b81516001600160401b0390811660a052602080840180516001600160a01b0390811660c05260408087018051831660e052815188519096168652925182169385019390935290511682820152517f2f56698ec552a5d53d27d6f4b3dd8b6989f6426b6151a36aff61160c1d07efdf9181900360600190a1620001b9816200026c565b5050620007d0565b336001600160a01b038216036200021b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200051c576000828281518110620002905762000290620007ba565b60200260200101519050600081600001519050806001600160401b0316600003620002ce5760405163c656089560e01b815260040160405180910390fd5b60608201516001600160a01b0316620002fa576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260076020526040902060018101546001600160a01b031662000400576200035c8284606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200052060201b60201c565b600282015560608301516001820180546001600160a01b039283166001600160a01b03199091161790556040808501518354610100600160481b03199190931669010000000000000000000216610100600160e81b031990921691909117610100178255516001600160401b03831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a16200046f565b606083015160018201546001600160a01b03908116911614158062000444575060408301518154690100000000000000000090046001600160a01b03908116911614155b156200046f5760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fa73c588738263db34ef8c1942db8f99559bc6696f6a812d42e76bafb4c0e8d309062000505908490815460ff811615158252600881901c6001600160401b0316602083015260481c6001600160a01b0390811660408301526001830154166060820152600290910154608082015260a00190565b60405180910390a25050508060010190506200026f565b5050565b60a0805160408051602081018590526001600160401b0380881692820192909252911660608201526001600160a01b0384166080820152600091016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005b557620005b56200057a565b60405290565b604051608081016001600160401b0381118282101715620005b557620005b56200057a565b604051601f8201601f191681016001600160401b03811182821017156200060b576200060b6200057a565b604052919050565b80516001600160401b03811681146200062b57600080fd5b919050565b80516001600160a01b03811681146200062b57600080fd5b6000808284036080808212156200065e57600080fd5b6060808312156200066e57600080fd5b6200067862000590565b9250620006858662000613565b835260206200069681880162000630565b818501526040620006aa6040890162000630565b604086015260608801519496506001600160401b0380861115620006cd57600080fd5b858901955089601f870112620006e257600080fd5b855181811115620006f757620006f76200057a565b62000707848260051b01620005e0565b818152848101925060079190911b87018401908b8211156200072857600080fd5b968401965b81881015620007a85786888d031215620007475760008081fd5b62000751620005bb565b6200075c8962000613565b8152858901518015158114620007725760008081fd5b818701526200078389860162000630565b8582015262000794878a0162000630565b81880152835296860196918401916200072d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051615fb46200082d6000396000818161021e01526131fe0152600081816101ef015281816115fc01526116b30152600081816101bf0152613120015260008181611c4f0152611c9b0152615fb46000f3fe608060405234801561001057600080fd5b506004361061018d5760003560e01c80637f63b711116100e3578063d2a15d351161008c578063f52121a511610066578063f52121a514610686578063f716f99f14610699578063ff888fb1146106ac57600080fd5b8063d2a15d3514610552578063e9d68a8e14610565578063f2fde38b1461067357600080fd5b80638da5cb5b116100bd5780638da5cb5b146104d2578063c673e584146104ed578063ccd37ba31461050d57600080fd5b80637f63b7111461049e57806385572ffb146104b15780638b364334146104bf57600080fd5b8063403b2d631161014557806369600bca1161011f57806369600bca1461036e5780637437ff9f1461038157806379ba50971461049657600080fd5b8063403b2d6314610328578063542625af1461033b5780635e36480c1461034e57600080fd5b80632d04ab76116101765780632d04ab76146102d9578063311cd513146102ee5780633f4b04aa1461030157600080fd5b806306285c6914610192578063181f5a7714610290575b600080fd5b61024e604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60408051825167ffffffffffffffff1681526020808401516001600160a01b039081169183019190915292820151909216908201526060015b60405180910390f35b6102cc6040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b604051610287919061423a565b6102ec6102e73660046142e5565b6106cf565b005b6102ec6102fc366004614398565b610a95565b600b5467ffffffffffffffff165b60405167ffffffffffffffff9091168152602001610287565b6102ec610336366004614545565b610afe565b6102ec610349366004614b69565b610cbb565b61036161035c366004614c94565b610e60565b6040516102879190614cf7565b6102ec61037c366004614d05565b610eb6565b61042d6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526004546001600160a01b03808216835263ffffffff74010000000000000000000000000000000000000000830481166020850152600160c01b8304811694840194909452600160e01b90910490921660608201526005548216608082015260065490911660a082015290565b6040516102879190600060c0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401528060a08501511660a08401525092915050565b6102ec610f21565b6102ec6104ac366004614d22565b610fdf565b6102ec61018d366004614e06565b61030f6104cd366004614e41565b610ff3565b6000546040516001600160a01b039091168152602001610287565b6105006104fb366004614e80565b611009565b6040516102879190614ee0565b61054461051b366004614f55565b67ffffffffffffffff919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610287565b6102ec610560366004614f81565b611167565b610616610573366004614d05565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525067ffffffffffffffff908116600090815260076020908152604091829020825160a081018452815460ff8116151582526101008104909516928101929092526001600160a01b0369010000000000000000009094048416928201929092526001820154909216606083015260020154608082015290565b6040516102879190600060a08201905082511515825267ffffffffffffffff602084015116602083015260408301516001600160a01b03808216604085015280606086015116606085015250506080830151608083015292915050565b6102ec610681366004614ff6565b611221565b6102ec610694366004615013565b611232565b6102ec6106a73660046150df565b611564565b6106bf6106ba36600461522a565b6115a6565b6040519015158152602001610287565b60006106dd878901896153bb565b805151519091501515806106f657508051602001515115155b156107f657600b5460208a01359067ffffffffffffffff808316911610156107b557600b805467ffffffffffffffff191667ffffffffffffffff831617905560065482516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691633937306f9161077e916004016155f9565b600060405180830381600087803b15801561079857600080fd5b505af11580156107ac573d6000803e3d6000fd5b505050506107f4565b8160200151516000036107f4576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109de5760008260200151828151811061081e5761081e615526565b6020026020010151905060008160000151905061083a81611667565b600061084582611769565b602084015151815491925067ffffffffffffffff90811661010090920416141580610887575060208084015190810151905167ffffffffffffffff9182169116115b156108d057825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526108c792919060040161560c565b60405180910390fd5b60408301518061090c576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600a602090815260408083208484529091529020541561097f5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016108c7565b6020808501510151610992906001615657565b825468ffffffffffffffff00191661010067ffffffffffffffff92831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016107f9565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610a0e919061567f565b60405180910390a1610a8a60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506117c9915050565b505050505050505050565b610ad5610aa48284018461571c565b6040805160008082526020820190925290610acf565b6060815260200190600190039081610aba5790505b50611b40565b604080516000808252602082019092529050610af86001858585858660006117c9565b50505050565b610b06611bf0565b60a08101516001600160a01b03161580610b28575080516001600160a01b0316155b15610b5f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a177401000000000000000000000000000000000000000063ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff19908116928e1692909217905560a0808e01805160068054909416908f161790925586519a8b5297518716988a0198909852925185169388019390935251909216958501959095525185169383019390935251909216908201527f0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c9060c00160405180910390a150565b610cc3611c4c565b815181518114610cff576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610e50576000848281518110610d1e57610d1e615526565b60200260200101519050600081602001515190506000858481518110610d4657610d46615526565b6020026020010151905080518214610d8a576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610e41576000828281518110610da957610da9615526565b6020026020010151905080600014158015610de4575084602001518281518110610dd557610dd5615526565b60200260200101516080015181105b15610e385784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016108c7565b50600101610d8d565b50505050806001019050610d02565b50610e5b8383611b40565b505050565b6000610e6e60016004615751565b6002610e7b60808561577a565b67ffffffffffffffff16610e8f91906157a1565b610e998585611ccd565b901c166003811115610ead57610ead614ccd565b90505b92915050565b610ebe611bf0565b600b805467ffffffffffffffff83811667ffffffffffffffff1983168117909355604080519190921680825260208201939093527f88ad9c61d6caf19a2af116a871802a03a31e680115a2dd20e8c08801d7c82f83910160405180910390a15050565b6001546001600160a01b03163314610f7b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108c7565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610fe7611bf0565b610ff081611d14565b50565b6000806110008484612025565b50949350505050565b61104c6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156110f557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116110d7575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561115757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611139575b5050505050815250509050919050565b61116f611bf0565b60005b81811015610e5b57600083838381811061118e5761118e615526565b9050604002018036038101906111a491906157b8565b90506111b381602001516115a6565b61121857805167ffffffffffffffff166000908152600a602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101611172565b611229611bf0565b610ff081612136565b33301461126b576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816112a8565b60408051808201909152600080825260208201528152602001906001900390816112815790505b5061014084015151909150156113095761130683610140015184602001516040516020016112e591906001600160a01b0391909116815260200190565b60408051601f198184030181529181528601518651610160880151876121ec565b90505b60006113158483612299565b6005549091506001600160a01b03168015611402576040517fa219f6e50000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063a219f6e59061136f9085906004016158a0565b600060405180830381600087803b15801561138957600080fd5b505af192505050801561139a575060015b611402573d8080156113c8576040519150601f19603f3d011682016040523d82523d6000602084013e6113cd565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016108c7919061423a565b6101208501515115801561141857506080850151155b8061142f575060408501516001600160a01b03163b155b8061146f5750604085015161146d906001600160a01b03167f85572ffb0000000000000000000000000000000000000000000000000000000061233c565b155b1561147b575050505050565b60048054608087015160408089015190517f3cf9798300000000000000000000000000000000000000000000000000000000815260009485946001600160a01b031693633cf97983936114d6938a93611388939291016158b3565b6000604051808303816000875af11580156114f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261151d9190810190615934565b50915091508161155b57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016108c7919061423a565b50505050505050565b61156c611bf0565b60005b81518110156115a25761159a82828151811061158d5761158d615526565b6020026020010151612358565b60010161156f565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611643573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb0919061598e565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015611702573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611726919061598e565b15610ff0576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108c7565b67ffffffffffffffff81166000908152600760205260408120805460ff16610eb0576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108c7565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906118288760a46159ab565b90508260600151156118705784516118419060206157a1565b865161184e9060206157a1565b6118599060a06159ab565b61186391906159ab565b61186d90826159ab565b90505b3681146118b2576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016108c7565b50815181146118fa5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016108c7565b611902611c4c565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561195057611950614ccd565b600281111561196157611961614ccd565b905250905060028160200151600281111561197e5761197e614ccd565b1480156119d25750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106119ba576119ba615526565b6000918252602090912001546001600160a01b031633145b611a08576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611aea576020820151611a239060016159be565b60ff16855114611a5f576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611a9a576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611aac9291906159d7565b604051908190038120611ac3918b906020016159e7565b604051602081830303815290604052805190602001209050611ae88a82888888612663565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611b7a576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611be957611be1858281518110611baf57611baf615526565b602002602001015184611bdb57858381518110611bce57611bce615526565b602002602001015161287a565b8361287a565b600101611b91565b5050505050565b6000546001600160a01b03163314611c4a5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108c7565b565b467f000000000000000000000000000000000000000000000000000000000000000014611c4a576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016108c7565b67ffffffffffffffff8216600090815260096020526040812081611cf26080856159fb565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b60005b81518110156115a2576000828281518110611d3457611d34615526565b602002602001015190506000816000015190508067ffffffffffffffff16600003611d8b576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608201516001600160a01b0316611dcf576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8116600090815260076020526040902060018101546001600160a01b0316611ef257611e298284606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b361311a565b600282015560608301516001820180546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19909116179055604080850151835468ffffffffffffffff001991909316690100000000000000000002167fffffff00000000000000000000000000000000000000000000000000000000ff909216919091176101001782555167ffffffffffffffff831681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611f78565b606083015160018201546001600160a01b039081169116141580611f35575060408301518154690100000000000000000090046001600160a01b03908116911614155b15611f78576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016108c7565b6020830151815490151560ff1990911617815560405167ffffffffffffffff8316907fa73c588738263db34ef8c1942db8f99559bc6696f6a812d42e76bafb4c0e8d309061200f908490815460ff811615158252600881901c67ffffffffffffffff16602083015260481c6001600160a01b0390811660408301526001830154166060820152600290910154608082015260a00190565b60405180910390a2505050806001019050611d17565b67ffffffffffffffff80831660009081526008602090815260408083206001600160a01b038616845290915281205490918291168082036121285767ffffffffffffffff8516600090815260076020526040902054690100000000000000000090046001600160a01b03168015612126576040517f856c82470000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015282169063856c824790602401602060405180830381865afa1580156120f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121199190615a22565b600193509350505061212f565b505b9150600090505b9250929050565b336001600160a01b0382160361218e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108c7565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8560005b875181101561228e5761226988828151811061220e5761220e615526565b60200260200101516020015188888888868151811061222f5761222f615526565b602002602001015180602001905181019061224a9190615a3f565b88878151811061225c5761225c615526565b602002602001015161319d565b82828151811061227b5761227b615526565b60209081029190910101526001016121f0565b509695505050505050565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff168152602001846020015160405160200161231191906001600160a01b0391909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b600061234783613516565b8015610ead5750610ead8383613562565b806040015160ff16600003612383576000604051631b3fab5160e11b81526004016108c79190615af4565b60208082015160ff808216600090815260029093526040832060018101549293909283921690036123d4576060840151600182018054911515620100000262ff000019909216919091179055612429565b6060840151600182015460ff6201000090910416151590151514612429576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016108c7565b60a08401518051601f60ff82161115612458576001604051631b3fab5160e11b81526004016108c79190615af4565b6124be85856003018054806020026020016040519081016040528092919081815260200182805480156124b457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612496575b5050505050613604565b8560600151156125d05761252c85856002018054806020026020016040519081016040528092919081815260200182805480156124b4576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311612496575050505050613604565b608086015180516125469060028701906020840190614148565b50805160018501805461ff00191661010060ff841690810291909117909155601f1015612589576002604051631b3fab5160e11b81526004016108c79190615af4565b6040880151612599906003615b0e565b60ff168160ff16116125c1576003604051631b3fab5160e11b81526004016108c79190615af4565b6125cd8783600161366d565b50505b6125dc8583600261366d565b81516125f19060038601906020850190614148565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361264a938a939260028b01929190615b2a565b60405180910390a161265b856137ed565b505050505050565b61266b6141b6565b835160005b8181101561287057600060018886846020811061268f5761268f615526565b61269c91901a601b6159be565b8985815181106126ae576126ae615526565b60200260200101518986815181106126c8576126c8615526565b602002602001015160405160008152602001604052604051612706949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612728573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561278957612789614ccd565b600281111561279a5761279a614ccd565b90525090506001816020015160028111156127b7576127b7614ccd565b146127ee576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061280557612805615526565b602002015115612841576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061285c5761285c615526565b911515602090920201525050600101612670565b5050505050505050565b815161288581611667565b600061289082611769565b60208501515190915060008190036128d3576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151518114612911576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561292c5761292c6143ec565b604051908082528060200260200182016040528015612955578160200160208202803683370190505b50905060005b82811015612a1a5760008760200151828151811061297b5761297b615526565b60200260200101519050612993818660020154613809565b8383815181106129a5576129a5615526565b6020026020010181815250508061018001518383815181106129c9576129c9615526565b602002602001015114612a11578061018001516040517f345039be0000000000000000000000000000000000000000000000000000000081526004016108c791815260200190565b5060010161295b565b506000612a31858389606001518a60800151613965565b905080600003612a79576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016108c7565b8551151560005b84811015610a8a57600089602001518281518110612aa057612aa0615526565b602002602001015190506000612aba898360600151610e60565b90506002816003811115612ad057612ad0614ccd565b03612b265760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050613112565b6000816003811115612b3a57612b3a614ccd565b1480612b5757506003816003811115612b5557612b55614ccd565b145b612ba75760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016108c7565b8315612c885760045460009074010000000000000000000000000000000000000000900463ffffffff16612bdb8742615751565b1190508080612bfb57506003826003811115612bf957612bf9614ccd565b145b612c3d576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b1660048201526024016108c7565b8a8481518110612c4f57612c4f615526565b6020026020010151600014612c82578a8481518110612c7057612c70615526565b60200260200101518360800181815250505b50612ced565b6000816003811115612c9c57612c9c614ccd565b14612ced5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c16600483015290911660248201526044016108c7565b600080612cfe8b8560200151612025565b915091508015612ded5760c084015167ffffffffffffffff16612d22836001615657565b67ffffffffffffffff1614612da55760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612d94928f9267ffffffffffffffff93841681529190921660208201526001600160a01b0391909116604082015260600190565b60405180910390a150505050613112565b67ffffffffffffffff8b81166000908152600860209081526040808320888301516001600160a01b031684529091529020805467ffffffffffffffff19169184169190911790555b6000836003811115612e0157612e01614ccd565b03612e925760c084015167ffffffffffffffff16612e20836001615657565b67ffffffffffffffff1614612e925760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612d94928f9267ffffffffffffffff93841681529190921660208201526001600160a01b0391909116604082015260600190565b60008d604001518681518110612eaa57612eaa615526565b6020026020010151905080518561014001515114612f0e5760608501516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808f16600483015290911660248201526044016108c7565b612f1e8c866060015160016139bb565b600080612f2b8784613a63565b91509150612f3e8e8860600151846139bb565b888015612f5c57506003826003811115612f5a57612f5a614ccd565b145b8015612f7a57506000866003811115612f7757612f77614ccd565b14155b15612fba57866101800151816040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526004016108c7929190615bb0565b6003826003811115612fce57612fce614ccd565b14158015612fee57506002826003811115612feb57612feb614ccd565b14155b1561302f578d8760600151836040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526004016108c793929190615bc9565b600086600381111561304357613043614ccd565b036130b15767ffffffffffffffff808f1660009081526008602090815260408083208b8301516001600160a01b0316845290915281208054909216919061308983615bef565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051613102929190615c16565b60405180910390a4505050505050505b600101612a80565b600081847f00000000000000000000000000000000000000000000000000000000000000008560405160200161317d949392919093845267ffffffffffffffff9283166020850152911660408301526001600160a01b0316606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b604080518082019091526000808252602082015260006131c08460200151613cad565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015613245573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132699190615c36565b90506001600160a01b03811615806132b157506132af6001600160a01b0382167faff2afbf0000000000000000000000000000000000000000000000000000000061233c565b155b156132f3576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016108c7565b6000806133be633907753760e01b6040518061010001604052808d81526020018b67ffffffffffffffff1681526020018c6001600160a01b031681526020018e8152602001876001600160a01b031681526020018a6000015181526020018a6040015181526020018981525060405160240161336f9190615c53565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152600454859063ffffffff600160e01b909104166113886084613cef565b5091509150816133e3578060405163e1cd550960e01b81526004016108c7919061423a565b805160201461342b5780516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016108c7565b6000818060200190518101906134419190615d2a565b604080516001600160a01b038d16602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526004549192506134c4918790600160c01b900463ffffffff166113886084613cef565b509093509150826134ea578160405163e1cd550960e01b81526004016108c7919061423a565b604080518082019091526001600160a01b03909516855260208501525091925050509695505050505050565b6000613542827f01ffc9a700000000000000000000000000000000000000000000000000000000613562565b8015610eb0575061355b826001600160e01b0319613562565b1592915050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156135ed575060208210155b80156135f95750600081115b979650505050505050565b60005b8151811015610e5b5760ff83166000908152600360205260408120835190919084908490811061363957613639615526565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613607565b60005b82518160ff161015610af8576000838260ff168151811061369357613693615526565b60200260200101519050600060028111156136b0576136b0614ccd565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156136ef576136ef614ccd565b14613710576004604051631b3fab5160e11b81526004016108c79190615af4565b6001600160a01b038116613750576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561377657613776614ccd565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156137d3576137d3614ccd565b021790555090505050806137e690615d43565b9050613670565b60ff8116610ff057600b805467ffffffffffffffff1916905550565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b610100015160405160200161389f9897969594939291906001600160a01b039889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016138d89190615d62565b604051602081830303815290604052805190602001208761016001516040516020016139049190615e17565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b600080613973858585613e15565b905061397e816115a6565b61398c5760009150506139b3565b67ffffffffffffffff86166000908152600a60209081526040808320938352929052205490505b949350505050565b600060026139ca60808561577a565b67ffffffffffffffff166139de91906157a1565b905060006139ec8585611ccd565b9050816139fb60016004615751565b901b191681836003811115613a1257613a12614ccd565b67ffffffffffffffff871660009081526009602052604081209190921b92909217918291613a416080886159fb565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a590613aa79087908790600401615e2a565b600060405180830381600087803b158015613ac157600080fd5b505af1925050508015613ad2575060015b613c92573d808015613b00576040519150601f19603f3d011682016040523d82523d6000602084013e613b05565b606091505b506000613b1182615f6f565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000006001600160e01b031982161480613b5b575063e1cd550960e01b6001600160e01b03198216145b80613b76575063046b337b60e51b6001600160e01b03198216145b80613baa57507f78ef8024000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b80613bde57507f0c3b563c000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b80613c1257507fae9b4ce9000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b80613c4657507f09c25325000000000000000000000000000000000000000000000000000000006001600160e01b03198216145b15613c57575060039250905061212f565b856101800151826040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526004016108c7929190615bb0565b50506040805160208101909152600081526002909250929050565b60008151602014613cd3578160405163046b337b60e51b81526004016108c7919061423a565b610eb082806020019051810190613cea9190615d2a565b6140b3565b6000606060008361ffff1667ffffffffffffffff811115613d1257613d126143ec565b6040519080825280601f01601f191660200182016040528015613d3c576020820181803683370190505b509150863b613d6f577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613da2577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ddb577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613dfe5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613e56576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613e6a57506101018111155b613e87576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613eb1576040516309bde33960e01b815260040160405180910390fd5b80600003613ede5786600081518110613ecc57613ecc615526565b60200260200101519350505050613196565b60008167ffffffffffffffff811115613ef957613ef96143ec565b604051908082528060200260200182016040528015613f22578160200160208202803683370190505b50905060008080805b8581101561404c5760006001821b8b811603613f865788851015613f6f578c5160018601958e918110613f6057613f60615526565b60200260200101519050613fa8565b8551600185019487918110613f6057613f60615526565b8b5160018401938d918110613f9d57613f9d615526565b602002602001015190505b600089861015613fd8578d5160018701968f918110613fc957613fc9615526565b60200260200101519050613ffa565b8651600186019588918110613fef57613fef615526565b602002602001015190505b8285111561401b576040516309bde33960e01b815260040160405180910390fd5b6140258282614107565b87848151811061403757614037615526565b60209081029190910101525050600101613f2b565b50600185038214801561405e57508683145b801561406957508581145b614086576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061409b5761409b615526565b60200260200101519750505050505050509392505050565b60006001600160a01b038211806140cb575061040082105b156141035760408051602081018490520160408051601f198184030181529082905263046b337b60e51b82526108c79160040161423a565b5090565b600081831061411f5761411a8284614125565b610ead565b610ead83835b604080516001602082015290810183905260608101829052600090608001613947565b8280548282559060005260206000209081019282156141aa579160200282015b828111156141aa578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190614168565b506141039291506141d5565b604051806103e00160405280601f906020820280368337509192915050565b5b8082111561410357600081556001016141d6565b60005b838110156142055781810151838201526020016141ed565b50506000910152565b600081518084526142268160208601602086016141ea565b601f01601f19169290920160200192915050565b602081526000610ead602083018461420e565b8060608101831015610eb057600080fd5b60008083601f84011261427057600080fd5b50813567ffffffffffffffff81111561428857600080fd5b60208301915083602082850101111561212f57600080fd5b60008083601f8401126142b257600080fd5b50813567ffffffffffffffff8111156142ca57600080fd5b6020830191508360208260051b850101111561212f57600080fd5b60008060008060008060008060e0898b03121561430157600080fd5b61430b8a8a61424d565b9750606089013567ffffffffffffffff8082111561432857600080fd5b6143348c838d0161425e565b909950975060808b013591508082111561434d57600080fd5b6143598c838d016142a0565b909750955060a08b013591508082111561437257600080fd5b5061437f8b828c016142a0565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156143ad57600080fd5b6143b7858561424d565b9250606084013567ffffffffffffffff8111156143d357600080fd5b6143df8682870161425e565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614425576144256143ec565b60405290565b6040805190810167ffffffffffffffff81118282101715614425576144256143ec565b6040516101a0810167ffffffffffffffff81118282101715614425576144256143ec565b60405160a0810167ffffffffffffffff81118282101715614425576144256143ec565b6040516080810167ffffffffffffffff81118282101715614425576144256143ec565b6040516060810167ffffffffffffffff81118282101715614425576144256143ec565b604051601f8201601f1916810167ffffffffffffffff81118282101715614504576145046143ec565b604052919050565b6001600160a01b0381168114610ff057600080fd5b803561452c8161450c565b919050565b803563ffffffff8116811461452c57600080fd5b600060c0828403121561455757600080fd5b61455f614402565b823561456a8161450c565b815261457860208401614531565b602082015261458960408401614531565b604082015261459a60608401614531565b606082015260808301356145ad8161450c565b608082015260a08301356145c08161450c565b60a08201529392505050565b600067ffffffffffffffff8211156145e6576145e66143ec565b5060051b60200190565b67ffffffffffffffff81168114610ff057600080fd5b803561452c816145f0565b8015158114610ff057600080fd5b803561452c81614611565b600067ffffffffffffffff821115614644576146446143ec565b50601f01601f191660200190565b600082601f83011261466357600080fd5b81356146766146718261462a565b6144db565b81815284602083860101111561468b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126146b957600080fd5b813560206146c9614671836145cc565b82815260069290921b840181019181810190868411156146e857600080fd5b8286015b8481101561228e57604081890312156147055760008081fd5b61470d61442b565b81356147188161450c565b815281850135858201528352918301916040016146ec565b600082601f83011261474157600080fd5b81356020614751614671836145cc565b82815260059290921b8401810191818101908684111561477057600080fd5b8286015b8481101561228e57803567ffffffffffffffff8111156147945760008081fd5b6147a28986838b0101614652565b845250918301918301614774565b60006101a082840312156147c357600080fd5b6147cb61444e565b90506147d682614606565b81526147e460208301614521565b60208201526147f560408301614521565b604082015261480660608301614606565b60608201526080820135608082015261482160a0830161461f565b60a082015261483260c08301614606565b60c082015261484360e08301614521565b60e082015261010082810135908201526101208083013567ffffffffffffffff8082111561487057600080fd5b61487c86838701614652565b8385015261014092508285013591508082111561489857600080fd5b6148a4868387016146a8565b838501526101609250828501359150808211156148c057600080fd5b506148cd85828601614730565b82840152505061018080830135818301525092915050565b600082601f8301126148f657600080fd5b81356020614906614671836145cc565b82815260059290921b8401810191818101908684111561492557600080fd5b8286015b8481101561228e57803567ffffffffffffffff8111156149495760008081fd5b6149578986838b01016147b0565b845250918301918301614929565b600082601f83011261497657600080fd5b81356020614986614671836145cc565b82815260059290921b840181019181810190868411156149a557600080fd5b8286015b8481101561228e57803567ffffffffffffffff8111156149c95760008081fd5b6149d78986838b0101614730565b8452509183019183016149a9565b600082601f8301126149f657600080fd5b81356020614a06614671836145cc565b8083825260208201915060208460051b870101935086841115614a2857600080fd5b602086015b8481101561228e5780358352918301918301614a2d565b600082601f830112614a5557600080fd5b81356020614a65614671836145cc565b82815260059290921b84018101918181019086841115614a8457600080fd5b8286015b8481101561228e57803567ffffffffffffffff80821115614aa95760008081fd5b9088019060a0828b03601f1901811315614ac35760008081fd5b614acb614472565b614ad6888501614606565b815260408085013584811115614aec5760008081fd5b614afa8e8b838901016148e5565b8a8401525060608086013585811115614b135760008081fd5b614b218f8c838a0101614965565b8385015250608091508186013585811115614b3c5760008081fd5b614b4a8f8c838a01016149e5565b9184019190915250919093013590830152508352918301918301614a88565b6000806040808486031215614b7d57600080fd5b833567ffffffffffffffff80821115614b9557600080fd5b614ba187838801614a44565b9450602091508186013581811115614bb857600080fd5b8601601f81018813614bc957600080fd5b8035614bd7614671826145cc565b81815260059190911b8201840190848101908a831115614bf657600080fd5b8584015b83811015614c8257803586811115614c125760008081fd5b8501603f81018d13614c245760008081fd5b87810135614c34614671826145cc565b81815260059190911b82018a0190898101908f831115614c545760008081fd5b928b01925b82841015614c725783358252928a0192908a0190614c59565b8652505050918601918601614bfa565b50809750505050505050509250929050565b60008060408385031215614ca757600080fd5b8235614cb2816145f0565b91506020830135614cc2816145f0565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614cf357614cf3614ccd565b9052565b60208101610eb08284614ce3565b600060208284031215614d1757600080fd5b8135613196816145f0565b60006020808385031215614d3557600080fd5b823567ffffffffffffffff811115614d4c57600080fd5b8301601f81018513614d5d57600080fd5b8035614d6b614671826145cc565b81815260079190911b82018301908381019087831115614d8a57600080fd5b928401925b828410156135f95760808489031215614da85760008081fd5b614db0614495565b8435614dbb816145f0565b815284860135614dca81614611565b81870152604085810135614ddd8161450c565b90820152606085810135614df08161450c565b9082015282526080939093019290840190614d8f565b600060208284031215614e1857600080fd5b813567ffffffffffffffff811115614e2f57600080fd5b820160a0818503121561319657600080fd5b60008060408385031215614e5457600080fd5b8235614e5f816145f0565b91506020830135614cc28161450c565b803560ff8116811461452c57600080fd5b600060208284031215614e9257600080fd5b610ead82614e6f565b60008151808452602080850194506020840160005b83811015614ed55781516001600160a01b031687529582019590820190600101614eb0565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614f2f60e0840182614e9b565b90506040840151601f198483030160c0850152614f4c8282614e9b565b95945050505050565b60008060408385031215614f6857600080fd5b8235614f73816145f0565b946020939093013593505050565b60008060208385031215614f9457600080fd5b823567ffffffffffffffff80821115614fac57600080fd5b818501915085601f830112614fc057600080fd5b813581811115614fcf57600080fd5b8660208260061b8501011115614fe457600080fd5b60209290920196919550909350505050565b60006020828403121561500857600080fd5b81356131968161450c565b6000806040838503121561502657600080fd5b823567ffffffffffffffff8082111561503e57600080fd5b61504a868387016147b0565b9350602085013591508082111561506057600080fd5b5061506d85828601614730565b9150509250929050565b600082601f83011261508857600080fd5b81356020615098614671836145cc565b8083825260208201915060208460051b8701019350868411156150ba57600080fd5b602086015b8481101561228e5780356150d28161450c565b83529183019183016150bf565b600060208083850312156150f257600080fd5b823567ffffffffffffffff8082111561510a57600080fd5b818501915085601f83011261511e57600080fd5b813561512c614671826145cc565b81815260059190911b8301840190848101908883111561514b57600080fd5b8585015b8381101561521d5780358581111561516657600080fd5b860160c0818c03601f1901121561517d5760008081fd5b615185614402565b8882013581526040615198818401614e6f565b8a83015260606151a9818501614e6f565b82840152608091506151bc82850161461f565b9083015260a083810135898111156151d45760008081fd5b6151e28f8d83880101615077565b838501525060c08401359150888211156151fc5760008081fd5b61520a8e8c84870101615077565b908301525084525091860191860161514f565b5098975050505050505050565b60006020828403121561523c57600080fd5b5035919050565b80356001600160e01b038116811461452c57600080fd5b600082601f83011261526b57600080fd5b8135602061527b614671836145cc565b82815260069290921b8401810191818101908684111561529a57600080fd5b8286015b8481101561228e57604081890312156152b75760008081fd5b6152bf61442b565b81356152ca816145f0565b81526152d7828601615243565b8186015283529183019160400161529e565b600082601f8301126152fa57600080fd5b8135602061530a614671836145cc565b82815260079290921b8401810191818101908684111561532957600080fd5b8286015b8481101561228e5780880360808112156153475760008081fd5b61534f6144b8565b823561535a816145f0565b81526040601f1983018113156153705760008081fd5b61537861442b565b925086840135615387816145f0565b835283810135615396816145f0565b838801528187019290925260608301359181019190915283529183019160800161532d565b600060208083850312156153ce57600080fd5b823567ffffffffffffffff808211156153e657600080fd5b818501915060408083880312156153fc57600080fd5b61540461442b565b83358381111561541357600080fd5b84016040818a03121561542557600080fd5b61542d61442b565b81358581111561543c57600080fd5b8201601f81018b1361544d57600080fd5b803561545b614671826145cc565b81815260069190911b8201890190898101908d83111561547a57600080fd5b928a01925b828410156154ca5787848f0312156154975760008081fd5b61549f61442b565b84356154aa8161450c565b81526154b7858d01615243565b818d0152825292870192908a019061547f565b8452505050818701359350848411156154e257600080fd5b6154ee8a85840161525a565b818801528252508385013591508282111561550857600080fd5b615514888386016152e9565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561559357835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161555c565b50508583015187820388850152805180835290840192506000918401905b808310156155ed578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906155b1565b50979650505050505050565b602081526000610ead602083018461553c565b67ffffffffffffffff83168152606081016131966020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561567857615678615641565b5092915050565b60006020808352606084516040808487015261569e606087018361553c565b87850151878203601f19016040890152805180835290860193506000918601905b8083101561521d57845167ffffffffffffffff8151168352878101516156fe89850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906156bf565b60006020828403121561572e57600080fd5b813567ffffffffffffffff81111561574557600080fd5b6139b384828501614a44565b81810381811115610eb057610eb0615641565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061579557615795615764565b92169190910692915050565b8082028115828204841417610eb057610eb0615641565b6000604082840312156157ca57600080fd5b6157d261442b565b82356157dd816145f0565b81526020928301359281019290925250919050565b60008151808452602080850194506020840160005b83811015614ed557815180516001600160a01b031688526020908101519088015260408701965090820190600101615807565b8051825267ffffffffffffffff60208201511660208301526000604082015160a0604085015261586d60a085018261420e565b905060608301518482036060860152615886828261420e565b91505060808301518482036080860152614f4c82826157f2565b602081526000610ead602083018461583a565b6080815260006158c6608083018761583a565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b600082601f83011261590057600080fd5b815161590e6146718261462a565b81815284602083860101111561592357600080fd5b6139b38260208301602087016141ea565b60008060006060848603121561594957600080fd5b835161595481614611565b602085015190935067ffffffffffffffff81111561597157600080fd5b61597d868287016158ef565b925050604084015190509250925092565b6000602082840312156159a057600080fd5b815161319681614611565b80820180821115610eb057610eb0615641565b60ff8181168382160190811115610eb057610eb0615641565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a1657615a16615764565b92169190910492915050565b600060208284031215615a3457600080fd5b8151613196816145f0565b600060208284031215615a5157600080fd5b815167ffffffffffffffff80821115615a6957600080fd5b9083019060608286031215615a7d57600080fd5b615a856144b8565b825182811115615a9457600080fd5b615aa0878286016158ef565b825250602083015182811115615ab557600080fd5b615ac1878286016158ef565b602083015250604083015182811115615ad957600080fd5b615ae5878286016158ef565b60408301525095945050505050565b6020810160058310615b0857615b08614ccd565b91905290565b60ff818116838216029081169081811461567857615678615641565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015615b845784546001600160a01b031683526001948501949284019201615b5f565b50508481036060860152615b988188614e9b565b935050505060ff831660808301529695505050505050565b8281526040602082015260006139b3604083018461420e565b67ffffffffffffffff848116825283166020820152606081016139b36040830184614ce3565b600067ffffffffffffffff808316818103615c0c57615c0c615641565b6001019392505050565b615c208184614ce3565b6040602082015260006139b3604083018461420e565b600060208284031215615c4857600080fd5b81516131968161450c565b6020815260008251610100806020850152615c7261012085018361420e565b91506020850151615c8f604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cc960a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615ce6848361420e565b935060c08701519150808685030160e0870152615d03848361420e565b935060e0870151915080868503018387015250615d20838261420e565b9695505050505050565b600060208284031215615d3c57600080fd5b5051919050565b600060ff821660ff8103615d5957615d59615641565b60010192915050565b6020808252825182820181905260009190848201906040850190845b81811015615db157835180516001600160a01b031684526020908101519084015260408301938501939250600101615d7e565b50909695505050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015615e0a57601f19868403018952615df883835161420e565b98840198925090830190600101615ddc565b5090979650505050505050565b602081526000610ead6020830184615dbd565b60408152615e4560408201845167ffffffffffffffff169052565b60006020840151615e6160608401826001600160a01b03169052565b5060408401516001600160a01b038116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c0840151610100615ec28185018367ffffffffffffffff169052565b60e08601519150610120615ee0818601846001600160a01b03169052565b81870151925061014091508282860152808701519250506101a06101608181870152615f106101e087018561420e565b9350828801519250603f19610180818887030181890152615f3186866157f2565b9550828a01519450818887030184890152615f4c8686615dbd565b9550808a01516101c089015250505050508281036020840152614f4c8185615dbd565b6000815160208301516001600160e01b031980821693506004831015615f9f5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI @@ -364,9 +360,9 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetExecutionState( return _EVM2EVMMultiOffRamp.Contract.GetExecutionState(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector, sequenceNumber) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) { var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getLatestPriceEpochAndRound") + err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getLatestPriceSequenceNumber") if err != nil { return *new(uint64), err @@ -378,12 +374,12 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetLatestPriceEpochAndRou } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceEpochAndRound(&_EVM2EVMMultiOffRamp.CallOpts) +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.CallOpts) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetLatestPriceEpochAndRound() (uint64, error) { - return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceEpochAndRound(&_EVM2EVMMultiOffRamp.CallOpts) +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetLatestPriceSequenceNumber() (uint64, error) { + return _EVM2EVMMultiOffRamp.Contract.GetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.CallOpts) } func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) { @@ -496,28 +492,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) IsBlessed(root [32 return _EVM2EVMMultiOffRamp.Contract.IsBlessed(&_EVM2EVMMultiOffRamp.CallOpts, root) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) IsUnpausedAndNotCursed(opts *bind.CallOpts, sourceChainSelector uint64) (bool, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "isUnpausedAndNotCursed", sourceChainSelector) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) IsUnpausedAndNotCursed(sourceChainSelector uint64) (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.IsUnpausedAndNotCursed(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) IsUnpausedAndNotCursed(sourceChainSelector uint64) (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.IsUnpausedAndNotCursed(&_EVM2EVMMultiOffRamp.CallOpts, sourceChainSelector) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { var out []interface{} err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "latestConfigDetails", ocrPluginType) @@ -562,28 +536,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) Owner() (common.Ad return _EVM2EVMMultiOffRamp.Contract.Owner(&_EVM2EVMMultiOffRamp.CallOpts) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) Paused(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "paused") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Paused() (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.Paused(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) Paused() (bool, error) { - return _EVM2EVMMultiOffRamp.Contract.Paused(&_EVM2EVMMultiOffRamp.CallOpts) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "typeAndVersion") @@ -678,18 +630,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ManuallyExecut return _EVM2EVMMultiOffRamp.Contract.ManuallyExecute(&_EVM2EVMMultiOffRamp.TransactOpts, reports, gasLimitOverrides) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "pause") -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Pause() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Pause(&_EVM2EVMMultiOffRamp.TransactOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Pause() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Pause(&_EVM2EVMMultiOffRamp.TransactOpts) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.contract.Transact(opts, "resetUnblessedRoots", rootToReset) } @@ -714,16 +654,16 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetDynamicConf return _EVM2EVMMultiOffRamp.Contract.SetDynamicConfig(&_EVM2EVMMultiOffRamp.TransactOpts, dynamicConfig) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setLatestPriceEpochAndRound", latestPriceEpochAndRound) +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetLatestPriceSequenceNumber(opts *bind.TransactOpts, latestPriceSequenceNumber uint64) (*types.Transaction, error) { + return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setLatestPriceSequenceNumber", latestPriceSequenceNumber) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetLatestPriceEpochAndRound(&_EVM2EVMMultiOffRamp.TransactOpts, latestPriceEpochAndRound) +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetLatestPriceSequenceNumber(latestPriceSequenceNumber uint64) (*types.Transaction, error) { + return _EVM2EVMMultiOffRamp.Contract.SetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.TransactOpts, latestPriceSequenceNumber) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetLatestPriceEpochAndRound(latestPriceEpochAndRound *big.Int) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetLatestPriceEpochAndRound(&_EVM2EVMMultiOffRamp.TransactOpts, latestPriceEpochAndRound) +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetLatestPriceSequenceNumber(latestPriceSequenceNumber uint64) (*types.Transaction, error) { + return _EVM2EVMMultiOffRamp.Contract.SetLatestPriceSequenceNumber(&_EVM2EVMMultiOffRamp.TransactOpts, latestPriceSequenceNumber) } func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) { @@ -750,18 +690,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) TransferOwners return _EVM2EVMMultiOffRamp.Contract.TransferOwnership(&_EVM2EVMMultiOffRamp.TransactOpts, to) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "unpause") -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) Unpause() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Unpause(&_EVM2EVMMultiOffRamp.TransactOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Unpause() (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.Unpause(&_EVM2EVMMultiOffRamp.TransactOpts) -} - type EVM2EVMMultiOffRampCommitReportAcceptedIterator struct { Event *EVM2EVMMultiOffRampCommitReportAccepted @@ -940,8 +868,11 @@ func (it *EVM2EVMMultiOffRampConfigSetIterator) Close() error { } type EVM2EVMMultiOffRampConfigSet struct { - StaticConfig EVM2EVMMultiOffRampStaticConfig - DynamicConfig EVM2EVMMultiOffRampDynamicConfig + OcrPluginType uint8 + ConfigDigest [32]byte + Signers []common.Address + Transmitters []common.Address + F uint8 Raw types.Log } @@ -997,8 +928,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet(log type return event, nil } -type EVM2EVMMultiOffRampConfigSet0Iterator struct { - Event *EVM2EVMMultiOffRampConfigSet0 +type EVM2EVMMultiOffRampDynamicConfigSetIterator struct { + Event *EVM2EVMMultiOffRampDynamicConfigSet contract *bind.BoundContract event string @@ -1009,7 +940,7 @@ type EVM2EVMMultiOffRampConfigSet0Iterator struct { fail error } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { +func (it *EVM2EVMMultiOffRampDynamicConfigSetIterator) Next() bool { if it.fail != nil { return false @@ -1018,7 +949,7 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet0) + it.Event = new(EVM2EVMMultiOffRampDynamicConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1033,7 +964,7 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet0) + it.Event = new(EVM2EVMMultiOffRampDynamicConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1048,36 +979,32 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Error() error { +func (it *EVM2EVMMultiOffRampDynamicConfigSetIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Close() error { +func (it *EVM2EVMMultiOffRampDynamicConfigSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampConfigSet0 struct { - OcrPluginType uint8 - ConfigDigest [32]byte - Signers []common.Address - Transmitters []common.Address - F uint8 +type EVM2EVMMultiOffRampDynamicConfigSet struct { + DynamicConfig EVM2EVMMultiOffRampDynamicConfig Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSet0Iterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterDynamicConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampDynamicConfigSetIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet0") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "DynamicConfigSet") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampConfigSet0Iterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampDynamicConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "DynamicConfigSet", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet0) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampDynamicConfigSet) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigSet0") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "DynamicConfigSet") if err != nil { return nil, err } @@ -1087,8 +1014,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *b select { case log := <-logs: - event := new(EVM2EVMMultiOffRampConfigSet0) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { + event := new(EVM2EVMMultiOffRampDynamicConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "DynamicConfigSet", log); err != nil { return err } event.Raw = log @@ -1109,9 +1036,9 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *b }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet0(log types.Log) (*EVM2EVMMultiOffRampConfigSet0, error) { - event := new(EVM2EVMMultiOffRampConfigSet0) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseDynamicConfigSet(log types.Log) (*EVM2EVMMultiOffRampDynamicConfigSet, error) { + event := new(EVM2EVMMultiOffRampDynamicConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "DynamicConfigSet", log); err != nil { return nil, err } event.Raw = log @@ -1265,8 +1192,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseExecutionStateChan return event, nil } -type EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator struct { - Event *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet +type EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator struct { + Event *EVM2EVMMultiOffRampLatestPriceSequenceNumberSet contract *bind.BoundContract event string @@ -1277,7 +1204,7 @@ type EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator struct { fail error } -func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Next() bool { +func (it *EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator) Next() bool { if it.fail != nil { return false @@ -1286,7 +1213,7 @@ func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) + it.Event = new(EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1301,7 +1228,7 @@ func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) + it.Event = new(EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1316,33 +1243,33 @@ func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Error() error { +func (it *EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator) Close() error { +func (it *EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet struct { - OldEpochAndRound *big.Int - NewEpochAndRound *big.Int - Raw types.Log +type EVM2EVMMultiOffRampLatestPriceSequenceNumberSet struct { + OldSequenceNumber uint64 + NewSequenceNumber uint64 + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterLatestPriceEpochAndRoundSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterLatestPriceSequenceNumberSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "LatestPriceEpochAndRoundSet") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "LatestPriceSequenceNumberSet") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "LatestPriceEpochAndRoundSet", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "LatestPriceSequenceNumberSet", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchLatestPriceEpochAndRoundSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchLatestPriceSequenceNumberSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "LatestPriceEpochAndRoundSet") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "LatestPriceSequenceNumberSet") if err != nil { return nil, err } @@ -1352,8 +1279,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchLatestPriceEpochAn select { case log := <-logs: - event := new(EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "LatestPriceEpochAndRoundSet", log); err != nil { + event := new(EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "LatestPriceSequenceNumberSet", log); err != nil { return err } event.Raw = log @@ -1374,9 +1301,9 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchLatestPriceEpochAn }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseLatestPriceEpochAndRoundSet(log types.Log) (*EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet, error) { - event := new(EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "LatestPriceEpochAndRoundSet", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseLatestPriceSequenceNumberSet(log types.Log) (*EVM2EVMMultiOffRampLatestPriceSequenceNumberSet, error) { + event := new(EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "LatestPriceSequenceNumberSet", log); err != nil { return nil, err } event.Raw = log @@ -1655,123 +1582,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferr return event, nil } -type EVM2EVMMultiOffRampPausedIterator struct { - Event *EVM2EVMMultiOffRampPaused - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampPausedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampPaused) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampPaused) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *EVM2EVMMultiOffRampPausedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampPausedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampPaused struct { - Account common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterPaused(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampPausedIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "Paused") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampPausedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "Paused", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampPaused) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "Paused") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampPaused) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Paused", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParsePaused(log types.Log) (*EVM2EVMMultiOffRampPaused, error) { - event := new(EVM2EVMMultiOffRampPaused) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Paused", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - type EVM2EVMMultiOffRampRootRemovedIterator struct { Event *EVM2EVMMultiOffRampRootRemoved @@ -2490,8 +2300,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainSelecto return event, nil } -type EVM2EVMMultiOffRampTransmittedIterator struct { - Event *EVM2EVMMultiOffRampTransmitted +type EVM2EVMMultiOffRampStaticConfigSetIterator struct { + Event *EVM2EVMMultiOffRampStaticConfigSet contract *bind.BoundContract event string @@ -2502,7 +2312,7 @@ type EVM2EVMMultiOffRampTransmittedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampStaticConfigSetIterator) Next() bool { if it.fail != nil { return false @@ -2511,7 +2321,7 @@ func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTransmitted) + it.Event = new(EVM2EVMMultiOffRampStaticConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2526,7 +2336,7 @@ func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTransmitted) + it.Event = new(EVM2EVMMultiOffRampStaticConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2541,44 +2351,32 @@ func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampTransmittedIterator) Error() error { +func (it *EVM2EVMMultiOffRampStaticConfigSetIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampTransmittedIterator) Close() error { +func (it *EVM2EVMMultiOffRampStaticConfigSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampTransmitted struct { - OcrPluginType uint8 - ConfigDigest [32]byte - SequenceNumber uint64 - Raw types.Log +type EVM2EVMMultiOffRampStaticConfigSet struct { + StaticConfig EVM2EVMMultiOffRampStaticConfig + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) { - - var ocrPluginTypeRule []interface{} - for _, ocrPluginTypeItem := range ocrPluginType { - ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) - } +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterStaticConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampStaticConfigSetIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "Transmitted", ocrPluginTypeRule) + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "StaticConfigSet") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampTransmittedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "Transmitted", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampStaticConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "StaticConfigSet", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) { - - var ocrPluginTypeRule []interface{} - for _, ocrPluginTypeItem := range ocrPluginType { - ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) - } +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampStaticConfigSet) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "Transmitted", ocrPluginTypeRule) + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "StaticConfigSet") if err != nil { return nil, err } @@ -2588,8 +2386,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTransmitted(opts * select { case log := <-logs: - event := new(EVM2EVMMultiOffRampTransmitted) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { + event := new(EVM2EVMMultiOffRampStaticConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "StaticConfigSet", log); err != nil { return err } event.Raw = log @@ -2610,17 +2408,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTransmitted(opts * }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) { - event := new(EVM2EVMMultiOffRampTransmitted) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseStaticConfigSet(log types.Log) (*EVM2EVMMultiOffRampStaticConfigSet, error) { + event := new(EVM2EVMMultiOffRampStaticConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "StaticConfigSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampUnpausedIterator struct { - Event *EVM2EVMMultiOffRampUnpaused +type EVM2EVMMultiOffRampTransmittedIterator struct { + Event *EVM2EVMMultiOffRampTransmitted contract *bind.BoundContract event string @@ -2631,7 +2429,7 @@ type EVM2EVMMultiOffRampUnpausedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampUnpausedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampTransmittedIterator) Next() bool { if it.fail != nil { return false @@ -2640,7 +2438,7 @@ func (it *EVM2EVMMultiOffRampUnpausedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampUnpaused) + it.Event = new(EVM2EVMMultiOffRampTransmitted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2655,7 +2453,7 @@ func (it *EVM2EVMMultiOffRampUnpausedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampUnpaused) + it.Event = new(EVM2EVMMultiOffRampTransmitted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2670,32 +2468,44 @@ func (it *EVM2EVMMultiOffRampUnpausedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampUnpausedIterator) Error() error { +func (it *EVM2EVMMultiOffRampTransmittedIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampUnpausedIterator) Close() error { +func (it *EVM2EVMMultiOffRampTransmittedIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampUnpaused struct { - Account common.Address - Raw types.Log +type EVM2EVMMultiOffRampTransmitted struct { + OcrPluginType uint8 + ConfigDigest [32]byte + SequenceNumber uint64 + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterUnpaused(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampUnpausedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "Unpaused") + var ocrPluginTypeRule []interface{} + for _, ocrPluginTypeItem := range ocrPluginType { + ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) + } + + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "Transmitted", ocrPluginTypeRule) if err != nil { return nil, err } - return &EVM2EVMMultiOffRampUnpausedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "Unpaused", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampTransmittedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "Transmitted", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampUnpaused) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "Unpaused") + var ocrPluginTypeRule []interface{} + for _, ocrPluginTypeItem := range ocrPluginType { + ocrPluginTypeRule = append(ocrPluginTypeRule, ocrPluginTypeItem) + } + + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "Transmitted", ocrPluginTypeRule) if err != nil { return nil, err } @@ -2705,8 +2515,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchUnpaused(opts *bin select { case log := <-logs: - event := new(EVM2EVMMultiOffRampUnpaused) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Unpaused", log); err != nil { + event := new(EVM2EVMMultiOffRampTransmitted) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { return err } event.Raw = log @@ -2727,9 +2537,9 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchUnpaused(opts *bin }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseUnpaused(log types.Log) (*EVM2EVMMultiOffRampUnpaused, error) { - event := new(EVM2EVMMultiOffRampUnpaused) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Unpaused", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) { + event := new(EVM2EVMMultiOffRampTransmitted) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "Transmitted", log); err != nil { return nil, err } event.Raw = log @@ -2742,18 +2552,16 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (genera return _EVM2EVMMultiOffRamp.ParseCommitReportAccepted(log) case _EVM2EVMMultiOffRamp.abi.Events["ConfigSet"].ID: return _EVM2EVMMultiOffRamp.ParseConfigSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["ConfigSet0"].ID: - return _EVM2EVMMultiOffRamp.ParseConfigSet0(log) + case _EVM2EVMMultiOffRamp.abi.Events["DynamicConfigSet"].ID: + return _EVM2EVMMultiOffRamp.ParseDynamicConfigSet(log) case _EVM2EVMMultiOffRamp.abi.Events["ExecutionStateChanged"].ID: return _EVM2EVMMultiOffRamp.ParseExecutionStateChanged(log) - case _EVM2EVMMultiOffRamp.abi.Events["LatestPriceEpochAndRoundSet"].ID: - return _EVM2EVMMultiOffRamp.ParseLatestPriceEpochAndRoundSet(log) + case _EVM2EVMMultiOffRamp.abi.Events["LatestPriceSequenceNumberSet"].ID: + return _EVM2EVMMultiOffRamp.ParseLatestPriceSequenceNumberSet(log) case _EVM2EVMMultiOffRamp.abi.Events["OwnershipTransferRequested"].ID: return _EVM2EVMMultiOffRamp.ParseOwnershipTransferRequested(log) case _EVM2EVMMultiOffRamp.abi.Events["OwnershipTransferred"].ID: return _EVM2EVMMultiOffRamp.ParseOwnershipTransferred(log) - case _EVM2EVMMultiOffRamp.abi.Events["Paused"].ID: - return _EVM2EVMMultiOffRamp.ParsePaused(log) case _EVM2EVMMultiOffRamp.abi.Events["RootRemoved"].ID: return _EVM2EVMMultiOffRamp.ParseRootRemoved(log) case _EVM2EVMMultiOffRamp.abi.Events["SkippedAlreadyExecutedMessage"].ID: @@ -2766,10 +2574,10 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (genera return _EVM2EVMMultiOffRamp.ParseSourceChainConfigSet(log) case _EVM2EVMMultiOffRamp.abi.Events["SourceChainSelectorAdded"].ID: return _EVM2EVMMultiOffRamp.ParseSourceChainSelectorAdded(log) + case _EVM2EVMMultiOffRamp.abi.Events["StaticConfigSet"].ID: + return _EVM2EVMMultiOffRamp.ParseStaticConfigSet(log) case _EVM2EVMMultiOffRamp.abi.Events["Transmitted"].ID: return _EVM2EVMMultiOffRamp.ParseTransmitted(log) - case _EVM2EVMMultiOffRamp.abi.Events["Unpaused"].ID: - return _EVM2EVMMultiOffRamp.ParseUnpaused(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) @@ -2781,19 +2589,19 @@ func (EVM2EVMMultiOffRampCommitReportAccepted) Topic() common.Hash { } func (EVM2EVMMultiOffRampConfigSet) Topic() common.Hash { - return common.HexToHash("0xf778ca28f5b9f37b5d23ffa5357592348ea60ec4e42b1dce5c857a5a65b276f7") + return common.HexToHash("0xab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547") } -func (EVM2EVMMultiOffRampConfigSet0) Topic() common.Hash { - return common.HexToHash("0xab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547") +func (EVM2EVMMultiOffRampDynamicConfigSet) Topic() common.Hash { + return common.HexToHash("0x0da37fd00459f4f5f0b8210d31525e4910ae674b8bab34b561d146bb45773a4c") } func (EVM2EVMMultiOffRampExecutionStateChanged) Topic() common.Hash { return common.HexToHash("0x8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df2") } -func (EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) Topic() common.Hash { - return common.HexToHash("0xf0d557bfce33e354b41885eb9264448726cfe51f486ffa69809d2bf565456444") +func (EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) Topic() common.Hash { + return common.HexToHash("0x88ad9c61d6caf19a2af116a871802a03a31e680115a2dd20e8c08801d7c82f83") } func (EVM2EVMMultiOffRampOwnershipTransferRequested) Topic() common.Hash { @@ -2804,10 +2612,6 @@ func (EVM2EVMMultiOffRampOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (EVM2EVMMultiOffRampPaused) Topic() common.Hash { - return common.HexToHash("0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258") -} - func (EVM2EVMMultiOffRampRootRemoved) Topic() common.Hash { return common.HexToHash("0x202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12") } @@ -2832,12 +2636,12 @@ func (EVM2EVMMultiOffRampSourceChainSelectorAdded) Topic() common.Hash { return common.HexToHash("0xf4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb9") } -func (EVM2EVMMultiOffRampTransmitted) Topic() common.Hash { - return common.HexToHash("0x198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0") +func (EVM2EVMMultiOffRampStaticConfigSet) Topic() common.Hash { + return common.HexToHash("0x2f56698ec552a5d53d27d6f4b3dd8b6989f6426b6151a36aff61160c1d07efdf") } -func (EVM2EVMMultiOffRampUnpaused) Topic() common.Hash { - return common.HexToHash("0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa") +func (EVM2EVMMultiOffRampTransmitted) Topic() common.Hash { + return common.HexToHash("0x198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0") } func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) Address() common.Address { @@ -2851,7 +2655,7 @@ type EVM2EVMMultiOffRampInterface interface { GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) - GetLatestPriceEpochAndRound(opts *bind.CallOpts) (uint64, error) + GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) GetMerkleRoot(opts *bind.CallOpts, sourceChainSelector uint64, root [32]byte) (*big.Int, error) @@ -2863,14 +2667,10 @@ type EVM2EVMMultiOffRampInterface interface { IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) - IsUnpausedAndNotCursed(opts *bind.CallOpts, sourceChainSelector uint64) (bool, error) - LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) Owner(opts *bind.CallOpts) (common.Address, error) - Paused(opts *bind.CallOpts) (bool, error) - TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) @@ -2885,20 +2685,16 @@ type EVM2EVMMultiOffRampInterface interface { ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) - Pause(opts *bind.TransactOpts) (*types.Transaction, error) - ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []EVM2EVMMultiOffRampUnblessedRoot) (*types.Transaction, error) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOffRampDynamicConfig) (*types.Transaction, error) - SetLatestPriceEpochAndRound(opts *bind.TransactOpts, latestPriceEpochAndRound *big.Int) (*types.Transaction, error) + SetLatestPriceSequenceNumber(opts *bind.TransactOpts, latestPriceSequenceNumber uint64) (*types.Transaction, error) SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - Unpause(opts *bind.TransactOpts) (*types.Transaction, error) - FilterCommitReportAccepted(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampCommitReportAcceptedIterator, error) WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampCommitReportAccepted) (event.Subscription, error) @@ -2911,11 +2707,11 @@ type EVM2EVMMultiOffRampInterface interface { ParseConfigSet(log types.Log) (*EVM2EVMMultiOffRampConfigSet, error) - FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSet0Iterator, error) + FilterDynamicConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampDynamicConfigSetIterator, error) - WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet0) (event.Subscription, error) + WatchDynamicConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampDynamicConfigSet) (event.Subscription, error) - ParseConfigSet0(log types.Log) (*EVM2EVMMultiOffRampConfigSet0, error) + ParseDynamicConfigSet(log types.Log) (*EVM2EVMMultiOffRampDynamicConfigSet, error) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMMultiOffRampExecutionStateChangedIterator, error) @@ -2923,11 +2719,11 @@ type EVM2EVMMultiOffRampInterface interface { ParseExecutionStateChanged(log types.Log) (*EVM2EVMMultiOffRampExecutionStateChanged, error) - FilterLatestPriceEpochAndRoundSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampLatestPriceEpochAndRoundSetIterator, error) + FilterLatestPriceSequenceNumberSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampLatestPriceSequenceNumberSetIterator, error) - WatchLatestPriceEpochAndRoundSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet) (event.Subscription, error) + WatchLatestPriceSequenceNumberSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampLatestPriceSequenceNumberSet) (event.Subscription, error) - ParseLatestPriceEpochAndRoundSet(log types.Log) (*EVM2EVMMultiOffRampLatestPriceEpochAndRoundSet, error) + ParseLatestPriceSequenceNumberSet(log types.Log) (*EVM2EVMMultiOffRampLatestPriceSequenceNumberSet, error) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferRequestedIterator, error) @@ -2941,12 +2737,6 @@ type EVM2EVMMultiOffRampInterface interface { ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferred, error) - FilterPaused(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampPausedIterator, error) - - WatchPaused(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampPaused) (event.Subscription, error) - - ParsePaused(log types.Log) (*EVM2EVMMultiOffRampPaused, error) - FilterRootRemoved(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampRootRemovedIterator, error) WatchRootRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampRootRemoved) (event.Subscription, error) @@ -2983,17 +2773,17 @@ type EVM2EVMMultiOffRampInterface interface { ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) - FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) + FilterStaticConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampStaticConfigSetIterator, error) - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) + WatchStaticConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampStaticConfigSet) (event.Subscription, error) - ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) + ParseStaticConfigSet(log types.Log) (*EVM2EVMMultiOffRampStaticConfigSet, error) - FilterUnpaused(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampUnpausedIterator, error) + FilterTransmitted(opts *bind.FilterOpts, ocrPluginType []uint8) (*EVM2EVMMultiOffRampTransmittedIterator, error) - WatchUnpaused(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampUnpaused) (event.Subscription, error) + WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted, ocrPluginType []uint8) (event.Subscription, error) - ParseUnpaused(log types.Log) (*EVM2EVMMultiOffRampUnpaused, error) + ParseTransmitted(log types.Log) (*EVM2EVMMultiOffRampTransmitted, error) ParseLog(log types.Log) (generated.AbigenLog, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index bd627364d8..de649f27e2 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 @@ -9,7 +9,7 @@ commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin c6f23bb7bb4f59807a0f3405557c6ad633f1ba441e12b44e135681290f22c51e +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 4c7bdddea3decee12887c5bd89648ed3b423bd31eefe586d5cb5c1bc8b883ffe evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin da3b401b00dae39a2851740d00f2ed81d498ad9287b7ab9276f8b10021743d20 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b6132cb22370d62b1b20174bbe832ec87df61f6ab65f7fe2515733bdd10a30f5 evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 383e9930fbc1b7fbb6554cc8857229d207fd6742e87c7fb1a37002347e8de8e2 From e5057ce79dc8ef431ac87a858f083fd74c280b29 Mon Sep 17 00:00:00 2001 From: Amir Y <83904651+amirylm@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:57:46 +0300 Subject: [PATCH 7/8] LM: increase transmit gas limit (#1061) ## Motivation The current value (`1e6`) might not be enough for extreme conditions ## Solution Increased gas limit to `5e6` #changed --- .changeset/wild-gifts-refuse.md | 5 +++++ core/services/relay/evm/liquidity_manager.go | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/wild-gifts-refuse.md diff --git a/.changeset/wild-gifts-refuse.md b/.changeset/wild-gifts-refuse.md new file mode 100644 index 0000000000..88bf8b05eb --- /dev/null +++ b/.changeset/wild-gifts-refuse.md @@ -0,0 +1,5 @@ +--- +"ccip": patch +--- + +Increased gas limit for LM transmitter to 5e6 #changed diff --git a/core/services/relay/evm/liquidity_manager.go b/core/services/relay/evm/liquidity_manager.go index fdb581abf4..41d10aac78 100644 --- a/core/services/relay/evm/liquidity_manager.go +++ b/core/services/relay/evm/liquidity_manager.go @@ -32,6 +32,10 @@ import ( relaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) +const ( + lmGasLimit = 5e6 +) + var ( ocr3ABI = evmtypes.MustGetABI(no_op_ocr3.NoOpOCR3MetaData.ABI) ) @@ -89,7 +93,7 @@ func (r *rebalancerRelayer) NewRebalancerProvider(ctx context.Context, rargs com tm, err2 := ocrcommon.NewTransmitter( chain.TxManager(), fromAddresses, - 1e6, // TODO: gas limit may vary depending on tx + lmGasLimit, fromAddresses[0], txmgr.NewSendEveryStrategy(), txmgrtypes.TransmitCheckerSpec[common.Address]{}, From 292ac452dd6aeac47f7e773ce81bd1944e63fa01 Mon Sep 17 00:00:00 2001 From: Makram Date: Fri, 21 Jun 2024 16:38:56 +0300 Subject: [PATCH 8/8] [feat] CCIP capability config contract (#858) ## Motivation The CCIP capability needs to fetch its configuration from somewhere - that somewhere is the CCIP capability configuration contract. ## Solution Implement the CCIP capability configuration contract in solidity. The solidity implementation almost matches the design doc exactly. --- contracts/gas-snapshots/ccip.gas-snapshot | 50 + .../scripts/native_solc_compile_all_ccip | 1 + .../CCIPCapabilityConfiguration.sol | 497 ++++++ .../interfaces/ICapabilityRegistry.sol | 23 + .../CCIPCapabilityConfiguration.t.sol | 1572 +++++++++++++++++ .../CCIPCapabilityConfigurationHelper.sol | 57 + .../ccip_capability_configuration.go | 1079 +++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/gethwrappers/ccip/go_generate.go | 1 + 9 files changed, 3281 insertions(+), 1 deletion(-) create mode 100644 contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol create mode 100644 contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol create mode 100644 contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol create mode 100644 contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol create mode 100644 core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 4af4b21269..d70f3da3f0 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -34,6 +34,56 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28789) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55208) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243659) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) +CCIPCapabilityConfigurationSetup:test_getCapabilityConfiguration_Success() (gas: 9561) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70645) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 350565) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 471510) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 440232) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) +CCIPCapabilityConfiguration_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 9028) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 303038) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49619) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32253) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 367516) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120877) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 156973) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 367292) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157040) +CCIPCapabilityConfiguration_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9648) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1044432) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23118) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1992348) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2595930) +CCIPCapabilityConfiguration__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1834017) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1055344) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1055375) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilityRegistryCanCall_Reverts() (gas: 9576) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 182909) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 342472) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 19116) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 266071) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14807) +CCIPCapabilityConfiguration_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9604) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 285383) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 282501) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 283422) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 283588) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 287815) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1068544) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 282309) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 284277) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_Success() (gas: 289222) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 285518) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1120660) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1119000) +CCIPCapabilityConfiguration_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9540) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2133850) CommitStore_constructor:test_Constructor_Success() (gas: 3091440) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 75331) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 2c209d69d6..661de2b842 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -75,6 +75,7 @@ compileContract ccip/RMN.sol compileContract ccip/ARMProxy.sol compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +compileContract ccip/capability/CCIPCapabilityConfiguration.sol # Test helpers compileContract ccip/test/helpers/BurnMintERC677Helper.sol diff --git a/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol b/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol new file mode 100644 index 0000000000..45ffe3da78 --- /dev/null +++ b/contracts/src/v0.8/ccip/capability/CCIPCapabilityConfiguration.sol @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ICapabilityRegistry} from "./interfaces/ICapabilityRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice CCIPCapabilityConfiguration stores the configuration for the CCIP capability. +/// We have two classes of configuration: chain configuration and DON (in the CapabilityRegistry sense) configuration. +/// Each chain will have a single configuration which includes information like the router address. +/// Each CR DON will have up to four configurations: for each of (commit, exec), one blue and one green configuration. +/// This is done in order to achieve "blue-green" deployments. +contract CCIPCapabilityConfiguration is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator { + using EnumerableSet for EnumerableSet.UintSet; + + /// @notice Emitted when a chain's configuration is set. + /// @param chainSelector The chain selector. + /// @param chainConfig The chain configuration. + event ChainConfigSet(uint64 chainSelector, ChainConfig chainConfig); + + /// @notice Emitted when a chain's configuration is removed. + /// @param chainSelector The chain selector. + event ChainConfigRemoved(uint64 chainSelector); + + error ChainConfigNotSetForChain(uint64 chainSelector); + error NodeNotInRegistry(bytes32 p2pId); + error OnlyCapabilityRegistryCanCall(); + error ChainSelectorNotFound(uint64 chainSelector); + error ChainSelectorNotSet(); + error TooManyOCR3Configs(); + error TooManySigners(); + error TooManyTransmitters(); + error TooManyBootstrapP2PIds(); + error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); + error NotEnoughTransmitters(uint256 got, uint256 minimum); + error FMustBePositive(); + error FChainMustBePositive(); + error FTooHigh(); + error InvalidPluginType(); + error OfframpAddressCannotBeZero(); + error InvalidConfigLength(uint256 length); + error InvalidConfigStateTransition(ConfigState currentState, ConfigState proposedState); + error NonExistentConfigTransition(); + error WrongConfigCount(uint64 got, uint64 expected); + error WrongConfigDigest(bytes32 got, bytes32 expected); + error WrongConfigDigestBlueGreen(bytes32 got, bytes32 expected); + + /// @notice PluginType indicates the type of plugin that the configuration is for. + /// @param Commit The configuration is for the commit plugin. + /// @param Execution The configuration is for the execution plugin. + enum PluginType { + Commit, + Execution + } + + /// @notice ConfigState indicates the state of the configuration. + /// A DON's configuration always starts out in the "Init" state - this is the starting state. + /// The only valid transition from "Init" is to the "Running" state - this is the first ever configuration. + /// The only valid transition from "Running" is to the "Staging" state - this is a blue/green proposal. + /// The only valid transition from "Staging" is back to the "Running" state - this is a promotion. + /// TODO: explain rollbacks? + enum ConfigState { + Init, + Running, + Staging + } + + /// @notice Chain configuration. + /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. + struct ChainConfig { + bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capability registry. + uint8 fChain; // The fault tolerance parameter of the chain. + bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. + } + + /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. + struct ChainConfigInfo { + uint64 chainSelector; + ChainConfig chainConfig; + } + + /// @notice OCR3 configuration. + struct OCR3Config { + PluginType pluginType; // ────────╮ The plugin that the configuration is for. + uint64 chainSelector; // | The (remote) chain that the configuration is for. + uint8 F; // | The "big F" parameter for the role DON. + uint64 offchainConfigVersion; // ─╯ The version of the offchain configuration. + bytes offrampAddress; // The remote chain offramp address. + bytes32[] bootstrapP2PIds; // The bootstrap P2P IDs of the oracles that are part of the role DON. + // len(p2pIds) == len(signers) == len(transmitters) == 3 * F + 1 + // NOTE: indexes matter here! The p2p ID at index i corresponds to the signer at index i and the transmitter at index i. + // This is crucial in order to build the oracle ID <-> peer ID mapping offchain. + bytes32[] p2pIds; // The P2P IDs of the oracles that are part of the role DON. + bytes[] signers; // The onchain signing keys of nodes in the don. + bytes[] transmitters; // The onchain transmitter keys of nodes in the don. + bytes offchainConfig; // The offchain configuration for the OCR3 protocol. Protobuf encoded. + } + + /// @notice OCR3 configuration with metadata, specifically the config count and the config digest. + struct OCR3ConfigWithMeta { + OCR3Config config; // The OCR3 configuration. + uint64 configCount; // The config count used to compute the config digest. + bytes32 configDigest; // The config digest of the OCR3 configuration. + } + + /// @notice Type and version override. + string public constant override typeAndVersion = "CCIPCapabilityConfiguration 1.6.0-dev"; + + /// @notice The canonical capability registry address. + address internal immutable i_capabilityRegistry; + + /// @notice chain configuration for each chain that CCIP is deployed on. + mapping(uint64 chainSelector => ChainConfig chainConfig) internal s_chainConfigurations; + + /// @notice All chains that are configured. + EnumerableSet.UintSet internal s_remoteChainSelectors; + + /// @notice OCR3 configurations for each DON. + /// Each CR DON will have a commit and execution configuration. + /// This means that a DON can have up to 4 configurations, since we are implementing blue/green deployments. + mapping(uint32 donId => mapping(PluginType pluginType => OCR3ConfigWithMeta[] ocr3Configs)) internal s_ocr3Configs; + + /// @notice The DONs that have been configured. + EnumerableSet.UintSet internal s_donIds; + + uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; + uint8 internal constant MAX_OCR3_CONFIGS_PER_DON = 4; + uint8 internal constant MAX_NUM_ORACLES = 31; + + /// @param capabilityRegistry the canonical capability registry address. + constructor(address capabilityRegistry) { + i_capabilityRegistry = capabilityRegistry; + } + + // ================================================================ + // │ Config Getters │ + // ================================================================ + + /// @notice Returns all the chain configurations. + /// @return The chain configurations. + // TODO: will this eventually hit the RPC max response size limit? + function getAllChainConfigs() external view returns (ChainConfigInfo[] memory) { + uint256[] memory chainSelectors = s_remoteChainSelectors.values(); + ChainConfigInfo[] memory chainConfigs = new ChainConfigInfo[](s_remoteChainSelectors.length()); + for (uint256 i = 0; i < chainSelectors.length; ++i) { + uint64 chainSelector = uint64(chainSelectors[i]); + chainConfigs[i] = + ChainConfigInfo({chainSelector: chainSelector, chainConfig: s_chainConfigurations[chainSelector]}); + } + return chainConfigs; + } + + /// @notice Returns the OCR configuration for the given don ID and plugin type. + /// @param donId The DON ID. + /// @param pluginType The plugin type. + /// @return The OCR3 configurations, up to 2 (blue and green). + function getOCRConfig(uint32 donId, PluginType pluginType) external view returns (OCR3ConfigWithMeta[] memory) { + return s_ocr3Configs[donId][pluginType]; + } + + // ================================================================ + // │ Capability Configuration │ + // ================================================================ + + /// @inheritdoc ICapabilityConfiguration + /// @dev The CCIP capability will fetch the configuration needed directly from this contract. + /// The offchain syncer will call this function, however, so its important that it doesn't revert. + function getCapabilityConfiguration(uint32 /* donId */ ) external pure override returns (bytes memory configuration) { + return bytes(""); + } + + /// @notice Called by the registry prior to the config being set for a particular DON. + function beforeCapabilityConfigSet( + bytes32[] calldata, /* nodes */ + bytes calldata config, + uint64, /* configCount */ + uint32 donId + ) external override { + if (msg.sender != i_capabilityRegistry) { + revert OnlyCapabilityRegistryCanCall(); + } + + OCR3Config[] memory ocr3Configs = abi.decode(config, (OCR3Config[])); + (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) = _groupByPluginType(ocr3Configs); + if (commitConfigs.length > 0) { + _updatePluginConfig(donId, PluginType.Commit, commitConfigs); + } + if (execConfigs.length > 0) { + _updatePluginConfig(donId, PluginType.Execution, execConfigs); + } + } + + function _updatePluginConfig(uint32 donId, PluginType pluginType, OCR3Config[] memory newConfig) internal { + OCR3ConfigWithMeta[] memory currentConfig = s_ocr3Configs[donId][pluginType]; + + // Validate the state transition being proposed, which is implicitly defined by the combination + // of lengths of the current and new configurations. + ConfigState currentState = _stateFromConfigLength(currentConfig.length); + ConfigState proposedState = _stateFromConfigLength(newConfig.length); + _validateConfigStateTransition(currentState, proposedState); + + // Build the new configuration with metadata and validate that the transition is valid. + OCR3ConfigWithMeta[] memory newConfigWithMeta = + _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, proposedState); + _validateConfigTransition(currentConfig, newConfigWithMeta); + + // Update contract state with new configuration if its valid. + // We won't run out of gas from this delete since the array is at most 2 elements long. + delete s_ocr3Configs[donId][pluginType]; + for (uint256 i = 0; i < newConfigWithMeta.length; ++i) { + s_ocr3Configs[donId][pluginType].push(newConfigWithMeta[i]); + } + } + + // ================================================================ + // │ Config State Machine │ + // ================================================================ + + /// @notice Determine the config state of the configuration from the length of the config. + /// @param configLen The length of the configuration. + /// @return The config state. + function _stateFromConfigLength(uint256 configLen) internal pure returns (ConfigState) { + if (configLen > 2) { + revert InvalidConfigLength(configLen); + } + return ConfigState(configLen); + } + + // the only valid state transitions are the following: + // init -> running (first ever config) + // running -> staging (blue/green proposal) + // staging -> running (promotion) + // everything else is invalid and should revert. + function _validateConfigStateTransition(ConfigState currentState, ConfigState newState) internal pure { + // TODO: may be able to save gas if we put this in the if condition. + bool initToRunning = currentState == ConfigState.Init && newState == ConfigState.Running; + bool runningToStaging = currentState == ConfigState.Running && newState == ConfigState.Staging; + bool stagingToRunning = currentState == ConfigState.Staging && newState == ConfigState.Running; + if (initToRunning || runningToStaging || stagingToRunning) { + return; + } + revert InvalidConfigStateTransition(currentState, newState); + } + + function _validateConfigTransition( + OCR3ConfigWithMeta[] memory currentConfig, + OCR3ConfigWithMeta[] memory newConfigWithMeta + ) internal pure { + uint256 currentConfigLen = currentConfig.length; + uint256 newConfigLen = newConfigWithMeta.length; + if (currentConfigLen == 0 && newConfigLen == 1) { + // Config counts always must start at 1 for the first ever config. + if (newConfigWithMeta[0].configCount != 1) { + revert WrongConfigCount(newConfigWithMeta[0].configCount, 1); + } + return; + } + + if (currentConfigLen == 1 && newConfigLen == 2) { + // On a blue/green proposal: + // * the config digest of the blue config must remain unchanged. + // * the green config count must be the blue config count + 1. + if (newConfigWithMeta[0].configDigest != currentConfig[0].configDigest) { + revert WrongConfigDigestBlueGreen(newConfigWithMeta[0].configDigest, currentConfig[0].configDigest); + } + if (newConfigWithMeta[1].configCount != currentConfig[0].configCount + 1) { + revert WrongConfigCount(newConfigWithMeta[1].configCount, currentConfig[0].configCount + 1); + } + return; + } + + if (currentConfigLen == 2 && newConfigLen == 1) { + // On a promotion, the green config digest must become the blue config digest. + if (newConfigWithMeta[0].configDigest != currentConfig[1].configDigest) { + revert WrongConfigDigest(newConfigWithMeta[0].configDigest, currentConfig[1].configDigest); + } + return; + } + + revert NonExistentConfigTransition(); + } + + /// @notice Computes a new configuration with metadata based on the current configuration and the new configuration. + /// @param donId The DON ID. + /// @param currentConfig The current configuration, including metadata. + /// @param newConfig The new configuration, without metadata. + /// @param currentState The current state of the configuration. + /// @param newState The new state of the configuration. + /// @return The new configuration with metadata. + function _computeNewConfigWithMeta( + uint32 donId, + OCR3ConfigWithMeta[] memory currentConfig, + OCR3Config[] memory newConfig, + ConfigState currentState, + ConfigState newState + ) internal view returns (OCR3ConfigWithMeta[] memory) { + uint64[] memory configCounts = new uint64[](newConfig.length); + + // Set config counts based on the only valid state transitions. + // Init -> Running (first ever config) + // Running -> Staging (blue/green proposal) + // Staging -> Running (promotion) + if (currentState == ConfigState.Init && newState == ConfigState.Running) { + // First ever config starts with config count == 1. + configCounts[0] = 1; + } else if (currentState == ConfigState.Running && newState == ConfigState.Staging) { + // On a blue/green proposal, the config count of the green config is the blue config count + 1. + configCounts[0] = currentConfig[0].configCount; + configCounts[1] = currentConfig[0].configCount + 1; + } else if (currentState == ConfigState.Staging && newState == ConfigState.Running) { + // On a promotion, the config count of the green config becomes the blue config count. + configCounts[0] = currentConfig[1].configCount; + } else { + revert InvalidConfigStateTransition(currentState, newState); + } + + OCR3ConfigWithMeta[] memory newConfigWithMeta = new OCR3ConfigWithMeta[](newConfig.length); + for (uint256 i = 0; i < configCounts.length; ++i) { + _validateConfig(newConfig[i]); + newConfigWithMeta[i] = OCR3ConfigWithMeta({ + config: newConfig[i], + configCount: configCounts[i], + configDigest: _computeConfigDigest(donId, configCounts[i], newConfig[i]) + }); + } + + return newConfigWithMeta; + } + + /// @notice Group the OCR3 configurations by plugin type for further processing. + /// @param ocr3Configs The OCR3 configurations to group. + function _groupByPluginType(OCR3Config[] memory ocr3Configs) + internal + pure + returns (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) + { + if (ocr3Configs.length > MAX_OCR3_CONFIGS_PER_DON) { + revert TooManyOCR3Configs(); + } + + // Declare with size 2 since we have a maximum of two configs per plugin type (blue, green). + // If we have less we will adjust the length later using mstore. + // If the caller provides more than 2 configs per plugin type, we will revert due to out of bounds + // access in the for loop below. + commitConfigs = new OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); + execConfigs = new OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); + uint256 commitCount; + uint256 execCount; + for (uint256 i = 0; i < ocr3Configs.length; ++i) { + if (ocr3Configs[i].pluginType == PluginType.Commit) { + commitConfigs[commitCount] = ocr3Configs[i]; + ++commitCount; + } else { + execConfigs[execCount] = ocr3Configs[i]; + ++execCount; + } + } + + // Adjust the length of the arrays to the actual number of configs. + assembly { + mstore(commitConfigs, commitCount) + mstore(execConfigs, execCount) + } + + return (commitConfigs, execConfigs); + } + + function _validateConfig(OCR3Config memory cfg) internal view { + if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); + if (cfg.pluginType != PluginType.Commit && cfg.pluginType != PluginType.Execution) revert InvalidPluginType(); + // TODO: can we do more sophisticated validation than this? + if (cfg.offrampAddress.length == 0) revert OfframpAddressCannotBeZero(); + if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); + + // Some of these checks below are done in OCR2/3Base config validation, so we do them again here. + // Role DON OCR configs will have all the Role DON signers but only a subset of transmitters. + if (cfg.signers.length > MAX_NUM_ORACLES) revert TooManySigners(); + if (cfg.transmitters.length > MAX_NUM_ORACLES) revert TooManyTransmitters(); + + // We check for chain config presence above, so fChain here must be non-zero. + uint256 minTransmittersLength = 3 * s_chainConfigurations[cfg.chainSelector].fChain + 1; + if (cfg.transmitters.length < minTransmittersLength) { + revert NotEnoughTransmitters(cfg.transmitters.length, minTransmittersLength); + } + if (cfg.F == 0) revert FMustBePositive(); + if (cfg.signers.length <= 3 * cfg.F) revert FTooHigh(); + + if (cfg.p2pIds.length != cfg.signers.length || cfg.p2pIds.length != cfg.transmitters.length) { + revert P2PIdsLengthNotMatching(cfg.p2pIds.length, cfg.signers.length, cfg.transmitters.length); + } + if (cfg.bootstrapP2PIds.length > cfg.p2pIds.length) revert TooManyBootstrapP2PIds(); + + // Check that the readers are in the capability registry. + // TODO: check for duplicate signers, duplicate p2p ids, etc. + // TODO: check that p2p ids in cfg.bootstrapP2PIds are included in cfg.p2pIds. + for (uint256 i = 0; i < cfg.signers.length; ++i) { + _ensureInRegistry(cfg.p2pIds[i]); + } + } + + /// @notice Computes the digest of the provided configuration. + /// @dev In traditional OCR config digest computation, block.chainid and address(this) are used + /// in order to further domain separate the digest. We can't do that here since the digest will + /// be used on remote chains; so we use the chain selector instead of block.chainid. The don ID + /// replaces the address(this) in the traditional computation. + /// @param donId The DON ID. + /// @param configCount The configuration count. + /// @param ocr3Config The OCR3 configuration. + /// @return The computed digest. + function _computeConfigDigest( + uint32 donId, + uint64 configCount, + OCR3Config memory ocr3Config + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + ocr3Config.chainSelector, + donId, + ocr3Config.pluginType, + ocr3Config.offrampAddress, + configCount, + ocr3Config.bootstrapP2PIds, + ocr3Config.p2pIds, + ocr3Config.signers, + ocr3Config.transmitters, + ocr3Config.F, + ocr3Config.offchainConfigVersion, + ocr3Config.offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x000a << (256 - 16); // 0x000a00..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + // ================================================================ + // │ Chain Configuration │ + // ================================================================ + + /// @notice Sets and/or removes chain configurations. + /// @param chainSelectorRemoves The chain configurations to remove. + /// @param chainConfigAdds The chain configurations to add. + function applyChainConfigUpdates( + uint64[] calldata chainSelectorRemoves, + ChainConfigInfo[] calldata chainConfigAdds + ) external onlyOwner { + // Process removals first. + for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { + // check if the chain selector is in s_remoteChainSelectors first. + if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { + revert ChainSelectorNotFound(chainSelectorRemoves[i]); + } + + delete s_chainConfigurations[chainSelectorRemoves[i]]; + s_remoteChainSelectors.remove(chainSelectorRemoves[i]); + + emit ChainConfigRemoved(chainSelectorRemoves[i]); + } + + // Process additions next. + for (uint256 i = 0; i < chainConfigAdds.length; ++i) { + ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; + bytes32[] memory readers = chainConfig.readers; + uint64 chainSelector = chainConfigAdds[i].chainSelector; + + // Verify that the provided readers are present in the capability registry. + for (uint256 j = 0; j < readers.length; j++) { + _ensureInRegistry(readers[j]); + } + + // Verify that fChain is positive. + if (chainConfig.fChain == 0) { + revert FChainMustBePositive(); + } + + s_chainConfigurations[chainSelector] = chainConfig; + s_remoteChainSelectors.add(chainSelector); + + emit ChainConfigSet(chainSelector, chainConfig); + } + } + + /// @notice Helper function to ensure that a node is in the capability registry. + /// @param p2pId The P2P ID of the node to check. + function _ensureInRegistry(bytes32 p2pId) internal view { + (ICapabilityRegistry.NodeInfo memory node,) = ICapabilityRegistry(i_capabilityRegistry).getNode(p2pId); + if (node.p2pId == bytes32("")) { + revert NodeNotInRegistry(p2pId); + } + } +} diff --git a/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol b/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol new file mode 100644 index 0000000000..85a98843c6 --- /dev/null +++ b/contracts/src/v0.8/ccip/capability/interfaces/ICapabilityRegistry.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface ICapabilityRegistry { + struct NodeInfo { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. + /// This key is guaranteed to be unique in the CapabilityRegistry. It is + /// used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + } + + /// @notice Gets a node's data + /// @param p2pId The P2P ID of the node to query for + /// @return NodeInfo The node data + /// @return configCount The number of times the node has been configured + function getNode(bytes32 p2pId) external view returns (NodeInfo memory, uint32 configCount); +} diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol new file mode 100644 index 0000000000..25e6d79c88 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/capability/CCIPCapabilityConfiguration.t.sol @@ -0,0 +1,1572 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {Test} from "forge-std/Test.sol"; + +import {CCIPCapabilityConfiguration} from "../../capability/CCIPCapabilityConfiguration.sol"; +import {ICapabilityRegistry} from "../../capability/interfaces/ICapabilityRegistry.sol"; +import {CCIPCapabilityConfigurationHelper} from "../helpers/CCIPCapabilityConfigurationHelper.sol"; + +contract CCIPCapabilityConfigurationSetup is Test { + address public constant OWNER = 0x82ae2B4F57CA5C1CBF8f744ADbD3697aD1a35AFe; + address public constant CAPABILITY_REGISTRY = 0x272aF4BF7FBFc4944Ed59F914Cd864DfD912D55e; + + CCIPCapabilityConfigurationHelper public s_ccipCC; + + function setUp() public { + changePrank(OWNER); + s_ccipCC = new CCIPCapabilityConfigurationHelper(CAPABILITY_REGISTRY); + } + + function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { + arr = new bytes32[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = keccak256(abi.encode(i, 1, seed)); + } + return arr; + } + + function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { + arr = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = abi.encodePacked(keccak256(abi.encode(i, 1, seed))); + } + return arr; + } + + function _subset(bytes32[] memory arr, uint256 start, uint256 end) internal pure returns (bytes32[] memory) { + bytes32[] memory subset = new bytes32[](end - start); + for (uint256 i = start; i < end; i++) { + subset[i - start] = arr[i]; + } + return subset; + } + + function _addChainConfig(uint256 numNodes) + internal + returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) + { + p2pIds = _makeBytes32Array(numNodes, 0); + signers = _makeBytesArray(numNodes, 10); + transmitters = _makeBytesArray(numNodes, 20); + for (uint256 i = 0; i < numNodes; i++) { + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, p2pIds[i]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(signers[i]), + p2pId: p2pIds[i], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + } + // Add chain selector for chain 1. + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](1); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: p2pIds, fChain: 1, config: bytes("config1")}) + }); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + return (p2pIds, signers, transmitters); + } + + function test_getCapabilityConfiguration_Success() public { + bytes memory capConfig = s_ccipCC.getCapabilityConfiguration(42 /* doesn't matter, not used */ ); + assertEq(capConfig.length, 0, "capability config length must be 0"); + } +} + +contract CCIPCapabilityConfiguration_chainConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test_applyChainConfigUpdates_addChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(2, adds[1].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPCapabilityConfiguration.ChainConfigInfo[] memory configs = s_ccipCC.getAllChainConfigs(); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + } + + function test_applyChainConfigUpdates_removeChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigSet(2, adds[1].chainConfig); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectEmit(); + emit CCIPCapabilityConfiguration.ChainConfigRemoved(1); + s_ccipCC.applyChainConfigUpdates(removes, new CCIPCapabilityConfiguration.ChainConfigInfo[](0)); + } + + // Reverts. + + function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.ChainSelectorNotFound.selector, 1)); + s_ccipCC.applyChainConfigUpdates(removes, new CCIPCapabilityConfiguration.ChainConfigInfo[](0)); + } + + function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](1); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NodeNotInRegistry.selector, chainReaders[0])); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + } + + function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPCapabilityConfiguration.ChainConfigInfo[] memory adds = new CCIPCapabilityConfiguration.ChainConfigInfo[](2); + adds[0] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 1, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPCapabilityConfiguration.ChainConfigInfo({ + chainSelector: 2, + chainConfig: CCIPCapabilityConfiguration.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain + }); + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + vm.expectRevert(CCIPCapabilityConfiguration.FChainMustBePositive.selector); + s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + } +} + +contract CCIPCapabilityConfiguration_validateConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test__validateConfig_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + s_ccipCC.validateConfig(config); + } + + // Reverts. + + function test__validateConfig_ChainSelectorNotSet_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 0, // invalid + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.ChainSelectorNotSet.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: bytes(""), // invalid + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.OfframpAddressCannotBeZero.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_ChainSelectorNotFound_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 2, // not set + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.ChainSelectorNotFound.selector, 2)); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManySigners_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManySigners.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManyTransmitters_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); + + // truncate signers but keep transmitters > 31 + assembly { + mstore(signers, 30) + } + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManyTransmitters.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmitters_Reverts() public { + // 32 > 31 (max num oracles) + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(31); + + // truncate transmitters to < 3 * fChain + 1 + // since fChain is 1 in this case, we need to truncate to 3 transmitters. + assembly { + mstore(transmitters, 3) + } + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NotEnoughTransmitters.selector, 3, 4)); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_FMustBePositive_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 0, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.FMustBePositive.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_FTooHigh_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 2, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.FTooHigh.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_P2PIdsLengthNotMatching_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // truncate the p2pIds length + assembly { + mstore(p2pIds, 3) + } + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.P2PIdsLengthNotMatching.selector, uint256(3), uint256(4), uint256(4) + ) + ); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_TooManyBootstrapP2PIds_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _makeBytes32Array(5, 0), // too many bootstrap p2pIds, 5 > 4 + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(CCIPCapabilityConfiguration.TooManyBootstrapP2PIds.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_NodeNotInRegistry_Reverts() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + bytes32 nonExistentP2PId = keccak256("notInRegistry"); + p2pIds[0] = nonExistentP2PId; + + vm.mockCall( + CAPABILITY_REGISTRY, + abi.encodeWithSelector(ICapabilityRegistry.getNode.selector, nonExistentP2PId), + abi.encode( + ICapabilityRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + hashedCapabilityIds: new bytes32[](0) + }), + uint32(1) + ) + ); + + // Config is for 4 nodes, so f == 1. + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.NodeNotInRegistry.selector, nonExistentP2PId)); + s_ccipCC.validateConfig(config); + } +} + +contract CCIPCapabilityConfiguration_ConfigStateMachine is CCIPCapabilityConfigurationSetup { + // Successful cases. + + function test__stateFromConfigLength_Success() public { + uint256 configLen = 0; + CCIPCapabilityConfiguration.ConfigState state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Init)); + + configLen = 1; + state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Running)); + + configLen = 2; + state = s_ccipCC.stateFromConfigLength(configLen); + assertEq(uint256(state), uint256(CCIPCapabilityConfiguration.ConfigState.Staging)); + } + + function test__validateConfigStateTransition_Success() public { + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Init, CCIPCapabilityConfiguration.ConfigState.Running + ); + + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Running, CCIPCapabilityConfiguration.ConfigState.Staging + ); + + s_ccipCC.validateConfigStateTransition( + CCIPCapabilityConfiguration.ConfigState.Staging, CCIPCapabilityConfiguration.ConfigState.Running + ); + } + + function test__computeConfigDigest_Success() public { + // config digest must change upon: + // - ocr config change (e.g plugin type, chain selector, etc.) + // - don id change + // - config count change + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(2, 10); + bytes[] memory transmitters = _makeBytesArray(2, 20); + CCIPCapabilityConfiguration.OCR3Config memory config = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + uint32 donId = 1; + uint32 configCount = 1; + + bytes32 configDigest1 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + donId = 2; + bytes32 configDigest2 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + donId = 1; + configCount = 2; + bytes32 configDigest3 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + configCount = 1; + config.pluginType = CCIPCapabilityConfiguration.PluginType.Execution; + bytes32 configDigest4 = s_ccipCC.computeConfigDigest(donId, configCount, config); + + assertNotEq(configDigest1, configDigest2, "config digests 1 and 2 must not match"); + assertNotEq(configDigest1, configDigest3, "config digests 1 and 3 must not match"); + assertNotEq(configDigest1, configDigest4, "config digests 1 and 4 must not match"); + + assertNotEq(configDigest2, configDigest3, "config digests 2 and 3 must not match"); + assertNotEq(configDigest2, configDigest4, "config digests 2 and 4 must not match"); + } + + function test_Fuzz__groupByPluginType_Success(uint256 numCommitCfgs, uint256 numExecCfgs) public { + vm.assume(numCommitCfgs >= 0 && numCommitCfgs < 3); + vm.assume(numExecCfgs >= 0 && numExecCfgs < 3); + + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = + new CCIPCapabilityConfiguration.OCR3Config[](numCommitCfgs + numExecCfgs); + for (uint256 i = 0; i < numCommitCfgs; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("commit", i) + }); + } + for (uint256 i = 0; i < numExecCfgs; i++) { + cfgs[numCommitCfgs + i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("exec", numCommitCfgs + i) + }); + } + ( + CCIPCapabilityConfiguration.OCR3Config[] memory commitCfgs, + CCIPCapabilityConfiguration.OCR3Config[] memory execCfgs + ) = s_ccipCC.groupByPluginType(cfgs); + + assertEq(commitCfgs.length, numCommitCfgs, "commitCfgs length must match"); + assertEq(execCfgs.length, numExecCfgs, "execCfgs length must match"); + for (uint256 i = 0; i < commitCfgs.length; i++) { + assertEq( + uint8(commitCfgs[i].pluginType), + uint8(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + assertEq(commitCfgs[i].offchainConfig, abi.encode("commit", i), "offchain config must match"); + } + for (uint256 i = 0; i < execCfgs.length; i++) { + assertEq( + uint8(execCfgs[i].pluginType), + uint8(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + assertEq(execCfgs[i].offchainConfig, abi.encode("exec", numCommitCfgs + i), "offchain config must match"); + } + } + + function test__computeNewConfigWithMeta_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Init; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Running; + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); + assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count must be 1"); + assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(newConfig[0].pluginType), "plugin type must match"); + assertEq(newConfigWithMeta[0].config.offchainConfig, newConfig[0].offchainConfig, "offchain config must match"); + assertEq( + newConfigWithMeta[0].configDigest, + s_ccipCC.computeConfigDigest(donId, 1, newConfig[0]), + "config digest must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__computeNewConfigWithMeta_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](2); + // existing blue config first. + newConfig[0] = blueConfig; + // green config next. + newConfig[1] = greenConfig; + + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Running; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Staging; + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + assertEq(newConfigWithMeta.length, 2, "new config with meta length must be 2"); + + assertEq(newConfigWithMeta[0].configCount, uint64(1), "config count of blue must be 1"); + assertEq( + uint8(newConfigWithMeta[0].config.pluginType), uint8(blueConfig.pluginType), "plugin type of blue must match" + ); + assertEq( + newConfigWithMeta[0].config.offchainConfig, blueConfig.offchainConfig, "offchain config of blue must match" + ); + assertEq( + newConfigWithMeta[0].configDigest, + s_ccipCC.computeConfigDigest(donId, 1, blueConfig), + "config digest of blue must match" + ); + + assertEq(newConfigWithMeta[1].configCount, uint64(2), "config count of green must be 2"); + assertEq( + uint8(newConfigWithMeta[1].config.pluginType), uint8(greenConfig.pluginType), "plugin type of green must match" + ); + assertEq( + newConfigWithMeta[1].config.offchainConfig, greenConfig.offchainConfig, "offchain config of green must match" + ); + assertEq( + newConfigWithMeta[1].configDigest, + s_ccipCC.computeConfigDigest(donId, 2, greenConfig), + "config digest of green must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__computeNewConfigWithMeta_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](1); + newConfig[0] = greenConfig; + + CCIPCapabilityConfiguration.ConfigState currentState = CCIPCapabilityConfiguration.ConfigState.Staging; + CCIPCapabilityConfiguration.ConfigState newState = CCIPCapabilityConfiguration.ConfigState.Running; + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfigWithMeta = + s_ccipCC.computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + + assertEq(newConfigWithMeta.length, 1, "new config with meta length must be 1"); + assertEq(newConfigWithMeta[0].configCount, uint64(2), "config count must be 2"); + assertEq(uint8(newConfigWithMeta[0].config.pluginType), uint8(greenConfig.pluginType), "plugin type must match"); + assertEq(newConfigWithMeta[0].config.offchainConfig, greenConfig.offchainConfig, "offchain config must match"); + assertEq( + newConfigWithMeta[0].configDigest, s_ccipCC.computeConfigDigest(donId, 2, greenConfig), "config digest must match" + ); + + // This ensures that the test case is using correct inputs. + s_ccipCC.validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function test__validateConfigTransition_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + // Reverts. + + function test_Fuzz__stateFromConfigLength_Reverts(uint256 configLen) public { + vm.assume(configLen > 2); + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigLength.selector, configLen)); + s_ccipCC.stateFromConfigLength(configLen); + } + + function test__groupByPluginType_threeCommitConfigs_Reverts() public { + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](3); + for (uint256 i = 0; i < 3; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("commit", i) + }); + } + vm.expectRevert(); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__groupByPluginType_threeExecutionConfigs_Reverts() public { + bytes32[] memory p2pIds = _makeBytes32Array(4, 0); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](3); + for (uint256 i = 0; i < 3; i++) { + cfgs[i] = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: abi.encode("exec", i) + }); + } + vm.expectRevert(); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__groupByPluginType_TooManyOCR3Configs_Reverts() public { + CCIPCapabilityConfiguration.OCR3Config[] memory cfgs = new CCIPCapabilityConfiguration.OCR3Config[](5); + vm.expectRevert(CCIPCapabilityConfiguration.TooManyOCR3Configs.selector); + s_ccipCC.groupByPluginType(cfgs); + } + + function test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 0, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](0); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.WrongConfigCount.selector, 0, 1)); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, blueConfig) // wrong config digest (due to diff config count) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.WrongConfigDigestBlueGreen.selector, + s_ccipCC.computeConfigDigest(donId, 3, blueConfig), + s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + ) + ); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + newConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 3, // wrong config count + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) + }); + + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.WrongConfigCount.selector, 3, 2)); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), + p2pIds: _makeBytes32Array(4, 0), + signers: _makeBytesArray(4, 10), + transmitters: _makeBytesArray(4, 20), + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](2); + currentConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 1, + config: blueConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + currentConfig[1] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + newConfig[0] = CCIPCapabilityConfiguration.OCR3ConfigWithMeta({ + configCount: 2, + config: greenConfig, + configDigest: s_ccipCC.computeConfigDigest(donId, 3, greenConfig) // wrong config digest + }); + + vm.expectRevert( + abi.encodeWithSelector( + CCIPCapabilityConfiguration.WrongConfigDigest.selector, + s_ccipCC.computeConfigDigest(donId, 3, greenConfig), + s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + ) + ); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } + + function test__validateConfigTransition_NonExistentConfigTransition_Reverts() public { + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory currentConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](3); + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory newConfig = + new CCIPCapabilityConfiguration.OCR3ConfigWithMeta[](1); + vm.expectRevert(CCIPCapabilityConfiguration.NonExistentConfigTransition.selector); + s_ccipCC.validateConfigTransition(currentConfig, newConfig); + } +} + +contract CCIPCapabilityConfiguration__updatePluginConfig is CCIPCapabilityConfigurationSetup { + // Successes. + + function test__updatePluginConfig_InitToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, configs); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 1, "don config length must be 1"); + assertEq(storedConfig[0].configCount, uint64(1), "config count must be 1"); + assertEq(uint256(storedConfig[0].config.pluginType), uint256(blueConfig.pluginType), "plugin type must match"); + } + + function test__updatePluginConfig_RunningToStaging_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // add blue config. + uint32 donId = 1; + CCIPCapabilityConfiguration.PluginType pluginType = CCIPCapabilityConfiguration.PluginType.Commit; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory startConfigs = new CCIPCapabilityConfiguration.OCR3Config[](1); + startConfigs[0] = blueConfig; + + // add blue AND green config to indicate an update. + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, startConfigs); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory blueAndGreen = new CCIPCapabilityConfiguration.OCR3Config[](2); + blueAndGreen[0] = blueConfig; + blueAndGreen[1] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, blueAndGreen); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 2, "don config length must be 2"); + // 0 index is blue config, 1 index is green config. + assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq( + uint256(storedConfig[1].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); + assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + } + + function test__updatePluginConfig_StagingToRunning_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + // add blue config. + uint32 donId = 1; + CCIPCapabilityConfiguration.PluginType pluginType = CCIPCapabilityConfiguration.PluginType.Commit; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory startConfigs = new CCIPCapabilityConfiguration.OCR3Config[](1); + startConfigs[0] = blueConfig; + + // add blue AND green config to indicate an update. + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, startConfigs); + CCIPCapabilityConfiguration.OCR3Config memory greenConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit-new") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory blueAndGreen = new CCIPCapabilityConfiguration.OCR3Config[](2); + blueAndGreen[0] = blueConfig; + blueAndGreen[1] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, blueAndGreen); + + // should see the updated config in the contract state. + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfig = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 2, "don config length must be 2"); + // 0 index is blue config, 1 index is green config. + assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq( + uint256(storedConfig[1].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); + assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + + // promote green to blue. + CCIPCapabilityConfiguration.OCR3Config[] memory promote = new CCIPCapabilityConfiguration.OCR3Config[](1); + promote[0] = greenConfig; + + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, promote); + + // should see the updated config in the contract state. + storedConfig = s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfig.length, 1, "don config length must be 1"); + assertEq(storedConfig[0].configCount, uint64(2), "config count must be 2"); + assertEq( + uint256(storedConfig[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must match" + ); + assertEq(storedConfig[0].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + } + + // Reverts. + function test__updatePluginConfig_InvalidConfigLength_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](3); + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigLength.selector, uint256(3))); + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, newConfig); + } + + function test__updatePluginConfig_InvalidConfigStateTransition_Reverts() public { + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config[] memory newConfig = new CCIPCapabilityConfiguration.OCR3Config[](2); + // 0 -> 2 is an invalid state transition. + vm.expectRevert(abi.encodeWithSelector(CCIPCapabilityConfiguration.InvalidConfigStateTransition.selector, 0, 2)); + s_ccipCC.updatePluginConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit, newConfig); + } +} + +contract CCIPCapabilityConfiguration_beforeCapabilityConfigSet is CCIPCapabilityConfigurationSetup { + // Successes. + function test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() public { + changePrank(CAPABILITY_REGISTRY); + + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](0); + bytes memory encodedConfigs = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encodedConfigs, 1, 1); + } + + function test_beforeCapabilityConfigSet_CommitConfigOnly_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedConfigs.length, 1, "config length must be 1"); + assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + } + + function test_beforeCapabilityConfigSet_ExecConfigOnly_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("exec") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](1); + configs[0] = blueConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Execution); + assertEq(storedConfigs.length, 1, "config length must be 1"); + assertEq(storedConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + } + + function test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() public { + (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + changePrank(CAPABILITY_REGISTRY); + + uint32 donId = 1; + CCIPCapabilityConfiguration.OCR3Config memory blueCommitConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Commit, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("commit") + }); + CCIPCapabilityConfiguration.OCR3Config memory blueExecConfig = CCIPCapabilityConfiguration.OCR3Config({ + pluginType: CCIPCapabilityConfiguration.PluginType.Execution, + offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), + chainSelector: 1, + bootstrapP2PIds: _subset(p2pIds, 0, 1), + p2pIds: p2pIds, + signers: signers, + transmitters: transmitters, + F: 1, + offchainConfigVersion: 30, + offchainConfig: bytes("exec") + }); + CCIPCapabilityConfiguration.OCR3Config[] memory configs = new CCIPCapabilityConfiguration.OCR3Config[](2); + configs[0] = blueExecConfig; + configs[1] = blueCommitConfig; + + bytes memory encoded = abi.encode(configs); + s_ccipCC.beforeCapabilityConfigSet(new bytes32[](0), encoded, 1, donId); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedExecConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Execution); + assertEq(storedExecConfigs.length, 1, "config length must be 1"); + assertEq(storedExecConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedExecConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Execution), + "plugin type must be execution" + ); + + CCIPCapabilityConfiguration.OCR3ConfigWithMeta[] memory storedCommitConfigs = + s_ccipCC.getOCRConfig(donId, CCIPCapabilityConfiguration.PluginType.Commit); + assertEq(storedCommitConfigs.length, 1, "config length must be 1"); + assertEq(storedCommitConfigs[0].configCount, uint64(1), "config count must be 1"); + assertEq( + uint256(storedCommitConfigs[0].config.pluginType), + uint256(CCIPCapabilityConfiguration.PluginType.Commit), + "plugin type must be commit" + ); + } + + // Reverts. + + function test_beforeCapabilityConfigSet_OnlyCapabilityRegistryCanCall_Reverts() public { + bytes32[] memory nodes = new bytes32[](0); + bytes memory config = bytes(""); + uint64 configCount = 1; + uint32 donId = 1; + vm.expectRevert(CCIPCapabilityConfiguration.OnlyCapabilityRegistryCanCall.selector); + s_ccipCC.beforeCapabilityConfigSet(nodes, config, configCount, donId); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol new file mode 100644 index 0000000000..7acc65f9bd --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPCapabilityConfigurationHelper.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {CCIPCapabilityConfiguration} from "../../capability/CCIPCapabilityConfiguration.sol"; + +contract CCIPCapabilityConfigurationHelper is CCIPCapabilityConfiguration { + constructor(address capabilityRegistry) CCIPCapabilityConfiguration(capabilityRegistry) {} + + function stateFromConfigLength(uint256 configLength) public pure returns (ConfigState) { + return _stateFromConfigLength(configLength); + } + + function validateConfigStateTransition(ConfigState currentState, ConfigState newState) public pure { + _validateConfigStateTransition(currentState, newState); + } + + function validateConfigTransition( + OCR3ConfigWithMeta[] memory currentConfig, + OCR3ConfigWithMeta[] memory newConfigWithMeta + ) public pure { + _validateConfigTransition(currentConfig, newConfigWithMeta); + } + + function computeNewConfigWithMeta( + uint32 donId, + OCR3ConfigWithMeta[] memory currentConfig, + OCR3Config[] memory newConfig, + ConfigState currentState, + ConfigState newState + ) public view returns (OCR3ConfigWithMeta[] memory) { + return _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); + } + + function groupByPluginType(OCR3Config[] memory ocr3Configs) + public + pure + returns (OCR3Config[] memory commitConfigs, OCR3Config[] memory execConfigs) + { + return _groupByPluginType(ocr3Configs); + } + + function computeConfigDigest( + uint32 donId, + uint64 configCount, + OCR3Config memory ocr3Config + ) public pure returns (bytes32) { + return _computeConfigDigest(donId, configCount, ocr3Config); + } + + function validateConfig(OCR3Config memory cfg) public view { + _validateConfig(cfg); + } + + function updatePluginConfig(uint32 donId, PluginType pluginType, OCR3Config[] memory newConfig) public { + _updatePluginConfig(donId, pluginType, newConfig); + } +} diff --git a/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go b/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go new file mode 100644 index 0000000000..88e100fd7b --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_capability_configuration/ccip_capability_configuration.go @@ -0,0 +1,1079 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_capability_configuration + +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 CCIPCapabilityConfigurationChainConfig struct { + Readers [][32]byte + FChain uint8 + Config []byte +} + +type CCIPCapabilityConfigurationChainConfigInfo struct { + ChainSelector uint64 + ChainConfig CCIPCapabilityConfigurationChainConfig +} + +type CCIPCapabilityConfigurationOCR3Config struct { + PluginType uint8 + ChainSelector uint64 + F uint8 + OffchainConfigVersion uint64 + OfframpAddress []byte + BootstrapP2PIds [][32]byte + P2pIds [][32]byte + Signers [][]byte + Transmitters [][]byte + OffchainConfig []byte +} + +type CCIPCapabilityConfigurationOCR3ConfigWithMeta struct { + Config CCIPCapabilityConfigurationOCR3Config + ConfigCount uint64 + ConfigDigest [32]byte +} + +var CCIPCapabilityConfigurationMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilityRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigNotSetForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPCapabilityConfiguration.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPCapabilityConfiguration.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilityRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyTransmitters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPCapabilityConfiguration.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumCCIPCapabilityConfiguration.PluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumCCIPCapabilityConfiguration.PluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPCapabilityConfiguration.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPCapabilityConfiguration.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620040563803806200405683398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b608051613e83620001d360003960008181610d640152610ff90152613e836000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80638da5cb5b11610076578063f2fde38b1161005b578063f2fde38b1461014e578063f442c89a14610161578063fba64a7c1461017457600080fd5b80638da5cb5b14610111578063ddc042a81461013957600080fd5b8063181f5a77146100a85780634bd0473f146100c657806379ba5097146100e65780638318ed5d146100f0575b600080fd5b6100b0610187565b6040516100bd9190612d12565b60405180910390f35b6100d96100d4366004612d56565b6101a3565b6040516100bd9190612e82565b6100ee610674565b005b6100b06100fe36600461305f565b5060408051602081019091526000815290565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bd565b610141610776565b6040516100bd91906130c0565b6100ee61015c366004613150565b610968565b6100ee61016f3660046131d2565b61097c565b6100ee610182366004613256565b610d4c565b604051806060016040528060258152602001613e526025913981565b63ffffffff821660009081526005602052604081206060918360018111156101cd576101cd612d8b565b60018111156101de576101de612d8b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561066757600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561025157610251612d8b565b600181111561026257610262612d8b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916102ba90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546102e690613313565b80156103335780601f1061030857610100808354040283529160200191610333565b820191906000526020600020905b81548152906001019060200180831161031657829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561038b57602002820191906000526020600020905b815481526020019060010190808311610377575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156103e357602002820191906000526020600020905b8154815260200190600101908083116103cf575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156104bd57838290600052602060002001805461043090613313565b80601f016020809104026020016040519081016040528092919081815260200182805461045c90613313565b80156104a95780601f1061047e576101008083540402835291602001916104a9565b820191906000526020600020905b81548152906001019060200180831161048c57829003601f168201915b505050505081526020019060010190610411565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b8282101561059657838290600052602060002001805461050990613313565b80601f016020809104026020016040519081016040528092919081815260200182805461053590613313565b80156105825780601f1061055757610100808354040283529160200191610582565b820191906000526020600020905b81548152906001019060200180831161056557829003601f168201915b5050505050815260200190600101906104ea565b5050505081526020016006820180546105ae90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546105da90613313565b80156106275780601f106105fc57610100808354040283529160200191610627565b820191906000526020600020905b81548152906001019060200180831161060a57829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161020c565b5050505090505b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006107846003610e0d565b905060006107926003610e21565b67ffffffffffffffff8111156107aa576107aa613366565b6040519080825280602002602001820160405280156107e357816020015b6107d0612a3f565b8152602001906001900390816107c85790505b50905060005b825181101561096157600083828151811061080657610806613395565b60209081029190910181015160408051808201825267ffffffffffffffff83168082526000908152600285528290208251815460808188028301810190955260608201818152959750929586019490939192849284919084018282801561088c57602002820191906000526020600020905b815481526020019060010190808311610878575b5050509183525050600182015460ff1660208201526002820180546040909201916108b690613313565b80601f01602080910402602001604051908101604052809291908181526020018280546108e290613313565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b50505050508152505081525083838151811061094d5761094d613395565b6020908102919091010152506001016107e9565b5092915050565b610970610e2b565b61097981610eae565b50565b610984610e2b565b60005b83811015610b6a576109cb8585838181106109a4576109a4613395565b90506020020160208101906109b991906133c4565b60039067ffffffffffffffff16610fa3565b610a35578484828181106109e1576109e1613395565b90506020020160208101906109f691906133c4565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f1565b60026000868684818110610a4b57610a4b613395565b9050602002016020810190610a6091906133c4565b67ffffffffffffffff1681526020810191909152604001600090812090610a878282612a87565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610abf600283016000612aa5565b5050610afd858583818110610ad657610ad6613395565b9050602002016020810190610aeb91906133c4565b60039067ffffffffffffffff16610fbb565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610b3157610b31613395565b9050602002016020810190610b4691906133c4565b60405167ffffffffffffffff909116815260200160405180910390a1600101610987565b5060005b81811015610d45576000838383818110610b8a57610b8a613395565b9050602002810190610b9c91906133df565b610baa90602081019061341d565b610bb39061361f565b80519091506000858585818110610bcc57610bcc613395565b9050602002810190610bde91906133df565b610bec9060208101906133c4565b905060005b8251811015610c2457610c1c838281518110610c0f57610c0f613395565b6020026020010151610fc7565b600101610bf1565b50826020015160ff16600003610c66576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120845180518693610c96928492910190612adf565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610ce39082613706565b50610cfd91506003905067ffffffffffffffff83166110e1565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08184604051610d2f929190613820565b60405180910390a1505050806001019050610b6e565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610dbb576040517f7b2485a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610dc9848601866138cb565b9050600080610dd7836110ed565b8151919350915015610def57610def84600084611346565b805115610e0257610e0284600183611346565b505050505050505050565b60606000610e1a83611b27565b9392505050565b600061066e825490565b60005473ffffffffffffffffffffffffffffffffffffffff163314610eac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f1565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610f2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f1565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610e1a565b6000610e1a8383611b83565b6040517f50c946fe000000000000000000000000000000000000000000000000000000008152600481018290526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906350c946fe90602401600060405180830381865afa158015611055573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261109b9190810190613add565b5060408101519091506110dd576040517f8907a4fa000000000000000000000000000000000000000000000000000000008152600481018390526024016106f1565b5050565b6000610e1a8383611c76565b606080600460ff168351111561112f576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b6111b36040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161114557505060408051600280825260608201909252919350602082015b61124b6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816111dd57905050905060008060005b855181101561133957600086828151811061128357611283613395565b60200260200101516000015160018111156112a0576112a0612d8b565b036112ed578581815181106112b7576112b7613395565b60200260200101518584815181106112d1576112d1613395565b6020026020010181905250826112e690613c0b565b9250611331565b8581815181106112ff576112ff613395565b602002602001015184838151811061131957611319613395565b60200260200101819052508161132e90613c0b565b91505b600101611266565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561136e5761136e612d8b565b600181111561137f5761137f612d8b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561180857600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156113f2576113f2612d8b565b600181111561140357611403612d8b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a010000000000000000000090910416606082015260018201805460809092019161145b90613313565b80601f016020809104026020016040519081016040528092919081815260200182805461148790613313565b80156114d45780601f106114a9576101008083540402835291602001916114d4565b820191906000526020600020905b8154815290600101906020018083116114b757829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561152c57602002820191906000526020600020905b815481526020019060010190808311611518575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561158457602002820191906000526020600020905b815481526020019060010190808311611570575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561165e5783829060005260206000200180546115d190613313565b80601f01602080910402602001604051908101604052809291908181526020018280546115fd90613313565b801561164a5780601f1061161f5761010080835404028352916020019161164a565b820191906000526020600020905b81548152906001019060200180831161162d57829003601f168201915b5050505050815260200190600101906115b2565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156117375783829060005260206000200180546116aa90613313565b80601f01602080910402602001604051908101604052809291908181526020018280546116d690613313565b80156117235780601f106116f857610100808354040283529160200191611723565b820191906000526020600020905b81548152906001019060200180831161170657829003601f168201915b50505050508152602001906001019061168b565b50505050815260200160068201805461174f90613313565b80601f016020809104026020016040519081016040528092919081815260200182805461177b90613313565b80156117c85780601f1061179d576101008083540402835291602001916117c8565b820191906000526020600020905b8154815290600101906020018083116117ab57829003601f168201915b505050919092525050508152600782015467ffffffffffffffff1660208083019190915260089092015460409091015290825260019290920191016113ad565b505050509050600061181a8251611cc5565b905060006118288451611cc5565b90506118348282611d17565b60006118438785878686611e0b565b905061184f84826121f7565b63ffffffff871660009081526005602052604081209087600181111561187757611877612d8b565b600181111561188857611888612d8b565b815260200190815260200160002060006118a29190612b2a565b60005b8151811015611b1d5763ffffffff88166000908152600560205260408120908860018111156118d6576118d6612d8b565b60018111156118e7576118e7612d8b565b815260200190815260200160002082828151811061190757611907613395565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690838181111561197157611971612d8b565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611a409082613706565b5060a08201518051611a5c916002840191602090910190612adf565b5060c08201518051611a78916003840191602090910190612adf565b5060e08201518051611a94916004840191602090910190612b4b565b506101008201518051611ab1916005840191602090910190612b4b565b506101208201516006820190611ac79082613706565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516008909101556001016118a5565b5050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7757602002820191906000526020600020905b815481526020019060010190808311611b63575b50505050509050919050565b60008181526001830160205260408120548015611c6c576000611ba7600183613c43565b8554909150600090611bbb90600190613c43565b9050818114611c20576000866000018281548110611bdb57611bdb613395565b9060005260206000200154905080876000018481548110611bfe57611bfe613395565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c3157611c31613c56565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061066e565b600091505061066e565b6000818152600183016020526040812054611cbd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561066e565b50600061066e565b60006002821115611d05576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016106f1565b81600281111561066e5761066e612d8b565b600080836002811115611d2c57611d2c612d8b565b148015611d4a57506001826002811115611d4857611d48612d8b565b145b905060006001846002811115611d6257611d62612d8b565b148015611d8057506002836002811115611d7e57611d7e612d8b565b145b905060006002856002811115611d9857611d98612d8b565b148015611db657506001846002811115611db457611db4612d8b565b145b90508280611dc15750815b80611dc95750805b15611dd5575050505050565b84846040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016106f1929190613c95565b60606000845167ffffffffffffffff811115611e2957611e29613366565b604051908082528060200260200182016040528015611e52578160200160208202803683370190505b5090506000846002811115611e6957611e69612d8b565b148015611e8757506001836002811115611e8557611e85612d8b565b145b15611ec857600181600081518110611ea157611ea1613395565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612030565b6001846002811115611edc57611edc612d8b565b148015611efa57506002836002811115611ef857611ef8612d8b565b145b15611f915785600081518110611f1257611f12613395565b60200260200101516020015181600081518110611f3157611f31613395565b602002602001019067ffffffffffffffff16908167ffffffffffffffff168152505085600081518110611f6657611f66613395565b6020026020010151602001516001611f7e9190613cb0565b81600181518110611ea157611ea1613395565b6002846002811115611fa557611fa5612d8b565b148015611fc357506001836002811115611fc157611fc1612d8b565b145b15611ffa5785600181518110611fdb57611fdb613395565b60200260200101516020015181600081518110611ea157611ea1613395565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016106f1929190613c95565b6000855167ffffffffffffffff81111561204c5761204c613366565b60405190808252806020026020018201604052801561210257816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161206a5790505b50905060005b82518110156121eb5761213387828151811061212657612126613395565b6020026020010151612576565b604051806060016040528088838151811061215057612150613395565b6020026020010151815260200184838151811061216f5761216f613395565b602002602001015167ffffffffffffffff1681526020016121c38b86858151811061219c5761219c613395565b60200260200101518b86815181106121b6576121b6613395565b602002602001015161296a565b8152508282815181106121d8576121d8613395565b6020908102919091010152600101612108565b50979650505050505050565b81518151811580156122095750806001145b156122ab578260008151811061222157612221613395565b60200260200101516020015167ffffffffffffffff166001146122a5578260008151811061225157612251613395565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016106f1565b50505050565b8160011480156122bb5750806002145b1561247157836000815181106122d3576122d3613395565b602002602001015160400151836000815181106122f2576122f2613395565b6020026020010151604001511461237e578260008151811061231657612316613395565b6020026020010151604001518460008151811061233557612335613395565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016106f1929190918252602082015260400190565b8360008151811061239157612391613395565b60200260200101516020015160016123a99190613cb0565b67ffffffffffffffff16836001815181106123c6576123c6613395565b60200260200101516020015167ffffffffffffffff16146122a557826001815181106123f4576123f4613395565b6020026020010151602001518460008151811061241357612413613395565b602002602001015160200151600161242b9190613cb0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016106f1565b8160021480156124815750806001145b15612544578360018151811061249957612499613395565b602002602001015160400151836000815181106124b8576124b8613395565b602002602001015160400151146122a557826000815181106124dc576124dc613395565b602002602001015160400151846001815181106124fb576124fb613395565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016106f1929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff166000036125be576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156125d3576125d3612d8b565b141580156125f457506001815160018111156125f1576125f1612d8b565b14155b1561262b576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80608001515160000361266a576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516126859060039067ffffffffffffffff16610fa3565b6126cd5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f1565b60e081015151601f101561270d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f101561274e576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff1660009081526002909152604081206001015461277e9060ff166003613cd1565b612789906001613ced565b60ff169050808261010001515110156127e057610100820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f1565b816040015160ff16600003612821576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040820151612831906003613cd1565b60ff168260e001515111612871576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c00151511415806128955750816101000151518260c001515114155b156128f05760c08201515160e083015151610100840151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016106f1565b8160c00151518260a00151511115612934576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8260e00151518110156129655761295d8360c001518281518110610c0f57610c0f613395565b600101612937565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d61012001516040516020016129be9c9b9a99989796959493929190613d71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a82604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b50805460008255906000526020600020908101906109799190612b9d565b508054612ab190613313565b6000825580601f10612ac1575050565b601f0160209004906000526020600020908101906109799190612b9d565b828054828255906000526020600020908101928215612b1a579160200282015b82811115612b1a578251825591602001919060010190612aff565b50612b26929150612b9d565b5090565b50805460008255600902906000526020600020908101906109799190612bb2565b828054828255906000526020600020908101928215612b91579160200282015b82811115612b915782518290612b819082613706565b5091602001919060010190612b6b565b50612b26929150612c73565b5b80821115612b265760008155600101612b9e565b80821115612b265780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612bf16001830182612aa5565b612bff600283016000612a87565b612c0d600383016000612a87565b612c1b600483016000612c90565b612c29600583016000612c90565b612c37600683016000612aa5565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612bb2565b80821115612b26576000612c878282612aa5565b50600101612c73565b50805460008255906000526020600020908101906109799190612c73565b6000815180845260005b81811015612cd457602081850181015186830182015201612cb8565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610e1a6020830184612cae565b63ffffffff8116811461097957600080fd5b8035612d4281612d25565b919050565b803560028110612d4257600080fd5b60008060408385031215612d6957600080fd5b8235612d7481612d25565b9150612d8260208401612d47565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612dca57612dca612d8b565b9052565b60008151808452602080850194506020840160005b83811015612dff57815187529582019590820190600101612de3565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015612e75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612e63838351612cae565b98840198925090830190600101612e29565b5090979650505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613051577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612ef08287018251612dba565b898101516080612f0b8189018367ffffffffffffffff169052565b8a830151915060a0612f21818a018460ff169052565b938301519360c09250612f3f8984018667ffffffffffffffff169052565b818401519450610140915060e082818b0152612f5f6101a08b0187612cae565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612f9e8885612dce565b97508587015195506101209350818c890301848d0152612fbe8887612dce565b9750828701519550818c890301858d0152612fd98887612e0a565b975080870151955050808b8803016101608c0152612ff78786612e0a565b9650828601519550808b8803016101808c015250505050506130198282612cae565b915050888201516130358a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eab565b509098975050505050505050565b60006020828403121561307157600080fd5b8135610e1a81612d25565b60008151606084526130916060850182612dce565b905060ff6020840151166020850152604083015184820360408601526130b78282612cae565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613051578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261313d8785018261307c565b95880195935050908601906001016130e9565b60006020828403121561316257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e1a57600080fd5b60008083601f84011261319857600080fd5b50813567ffffffffffffffff8111156131b057600080fd5b6020830191508360208260051b85010111156131cb57600080fd5b9250929050565b600080600080604085870312156131e857600080fd5b843567ffffffffffffffff8082111561320057600080fd5b61320c88838901613186565b9096509450602087013591508082111561322557600080fd5b5061323287828801613186565b95989497509550505050565b803567ffffffffffffffff81168114612d4257600080fd5b6000806000806000806080878903121561326f57600080fd5b863567ffffffffffffffff8082111561328757600080fd5b6132938a838b01613186565b909850965060208901359150808211156132ac57600080fd5b818901915089601f8301126132c057600080fd5b8135818111156132cf57600080fd5b8a60208285010111156132e157600080fd5b6020830196508095505050506132f96040880161323e565b915061330760608801612d37565b90509295509295509295565b600181811c9082168061332757607f821691505b602082108103613360577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156133d657600080fd5b610e1a8261323e565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261341357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261341357600080fd5b604051610140810167ffffffffffffffff8111828210171561347557613475613366565b60405290565b6040516080810167ffffffffffffffff8111828210171561347557613475613366565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156134e5576134e5613366565b604052919050565b600067ffffffffffffffff82111561350757613507613366565b5060051b60200190565b600082601f83011261352257600080fd5b81356020613537613532836134ed565b61349e565b8083825260208201915060208460051b87010193508684111561355957600080fd5b602086015b84811015613575578035835291830191830161355e565b509695505050505050565b803560ff81168114612d4257600080fd5b600082601f8301126135a257600080fd5b813567ffffffffffffffff8111156135bc576135bc613366565b6135ed60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161349e565b81815284602083860101111561360257600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561363157600080fd5b6040516060810167ffffffffffffffff828210818311171561365557613655613366565b81604052843591508082111561366a57600080fd5b61367636838701613511565b835261368460208601613580565b6020840152604085013591508082111561369d57600080fd5b506136aa36828601613591565b60408301525092915050565b601f821115612965576000816000526020600020601f850160051c810160208610156136df5750805b601f850160051c820191505b818110156136fe578281556001016136eb565b505050505050565b815167ffffffffffffffff81111561372057613720613366565b6137348161372e8454613313565b846136b6565b602080601f83116001811461378757600084156137515750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556136fe565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156137d4578886015182559484019460019091019084016137b5565b508582101561381057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613843604083018461307c565b949350505050565b600082601f83011261385c57600080fd5b8135602061386c613532836134ed565b82815260059290921b8401810191818101908684111561388b57600080fd5b8286015b8481101561357557803567ffffffffffffffff8111156138af5760008081fd5b6138bd8986838b0101613591565b84525091830191830161388f565b600060208083850312156138de57600080fd5b823567ffffffffffffffff808211156138f657600080fd5b818501915085601f83011261390a57600080fd5b8135613918613532826134ed565b81815260059190911b8301840190848101908883111561393757600080fd5b8585015b83811015613ac55780358581111561395257600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561398757600080fd5b61398f613451565b61399a898301612d47565b81526139a86040830161323e565b898201526139b860608301613580565b60408201526139c96080830161323e565b606082015260a0820135878111156139e057600080fd5b6139ee8d8b83860101613591565b60808301525060c082013587811115613a0657600080fd5b613a148d8b83860101613511565b60a08301525060e082013587811115613a2c57600080fd5b613a3a8d8b83860101613511565b60c0830152506101008083013588811115613a5457600080fd5b613a628e8c8387010161384b565b60e0840152506101208084013589811115613a7c57600080fd5b613a8a8f8d8388010161384b565b8385015250610140840135915088821115613aa457600080fd5b613ab28e8c84870101613591565b908301525084525091860191860161393b565b5098975050505050505050565b8051612d4281612d25565b60008060408385031215613af057600080fd5b825167ffffffffffffffff80821115613b0857600080fd5b9084019060808287031215613b1c57600080fd5b613b2461347b565b8251613b2f81612d25565b81526020838101518183015260408085015190830152606084015183811115613b5757600080fd5b80850194505087601f850112613b6c57600080fd5b83519250613b7c613532846134ed565b83815260059390931b84018101928181019089851115613b9b57600080fd5b948201945b84861015613bb957855182529482019490820190613ba0565b8060608501525050819550613bcf818801613ad2565b9450505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613c3c57613c3c613bdc565b5060010190565b8181038181111561066e5761066e613bdc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60038110612dca57612dca612d8b565b60408101613ca38285613c85565b610e1a6020830184613c85565b67ffffffffffffffff81811683821601908082111561096157610961613bdc565b60ff818116838216029081169081811461096157610961613bdc565b60ff818116838216019081111561066e5761066e613bdc565b60008282518085526020808601955060208260051b8401016020860160005b84811015612e75577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952613d5f838351612cae565b98840198925090830190600101613d25565b67ffffffffffffffff8d16815263ffffffff8c166020820152613d97604082018c612dba565b61018060608201526000613daf61018083018c612cae565b67ffffffffffffffff8b16608084015282810360a0840152613dd1818b612dce565b905082810360c0840152613de5818a612dce565b905082810360e0840152613df98189613d06565b9050828103610100840152613e0e8188613d06565b60ff8716610120850152905067ffffffffffffffff8516610140840152828103610160840152613e3e8185612cae565b9f9e50505050505050505050505050505056fe434349504361706162696c697479436f6e66696775726174696f6e20312e362e302d646576a164736f6c6343000818000a", +} + +var CCIPCapabilityConfigurationABI = CCIPCapabilityConfigurationMetaData.ABI + +var CCIPCapabilityConfigurationBin = CCIPCapabilityConfigurationMetaData.Bin + +func DeployCCIPCapabilityConfiguration(auth *bind.TransactOpts, backend bind.ContractBackend, capabilityRegistry common.Address) (common.Address, *types.Transaction, *CCIPCapabilityConfiguration, error) { + parsed, err := CCIPCapabilityConfigurationMetaData.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(CCIPCapabilityConfigurationBin), backend, capabilityRegistry) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CCIPCapabilityConfiguration{address: address, abi: *parsed, CCIPCapabilityConfigurationCaller: CCIPCapabilityConfigurationCaller{contract: contract}, CCIPCapabilityConfigurationTransactor: CCIPCapabilityConfigurationTransactor{contract: contract}, CCIPCapabilityConfigurationFilterer: CCIPCapabilityConfigurationFilterer{contract: contract}}, nil +} + +type CCIPCapabilityConfiguration struct { + address common.Address + abi abi.ABI + CCIPCapabilityConfigurationCaller + CCIPCapabilityConfigurationTransactor + CCIPCapabilityConfigurationFilterer +} + +type CCIPCapabilityConfigurationCaller struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationTransactor struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationFilterer struct { + contract *bind.BoundContract +} + +type CCIPCapabilityConfigurationSession struct { + Contract *CCIPCapabilityConfiguration + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CCIPCapabilityConfigurationCallerSession struct { + Contract *CCIPCapabilityConfigurationCaller + CallOpts bind.CallOpts +} + +type CCIPCapabilityConfigurationTransactorSession struct { + Contract *CCIPCapabilityConfigurationTransactor + TransactOpts bind.TransactOpts +} + +type CCIPCapabilityConfigurationRaw struct { + Contract *CCIPCapabilityConfiguration +} + +type CCIPCapabilityConfigurationCallerRaw struct { + Contract *CCIPCapabilityConfigurationCaller +} + +type CCIPCapabilityConfigurationTransactorRaw struct { + Contract *CCIPCapabilityConfigurationTransactor +} + +func NewCCIPCapabilityConfiguration(address common.Address, backend bind.ContractBackend) (*CCIPCapabilityConfiguration, error) { + abi, err := abi.JSON(strings.NewReader(CCIPCapabilityConfigurationABI)) + if err != nil { + return nil, err + } + contract, err := bindCCIPCapabilityConfiguration(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfiguration{address: address, abi: abi, CCIPCapabilityConfigurationCaller: CCIPCapabilityConfigurationCaller{contract: contract}, CCIPCapabilityConfigurationTransactor: CCIPCapabilityConfigurationTransactor{contract: contract}, CCIPCapabilityConfigurationFilterer: CCIPCapabilityConfigurationFilterer{contract: contract}}, nil +} + +func NewCCIPCapabilityConfigurationCaller(address common.Address, caller bind.ContractCaller) (*CCIPCapabilityConfigurationCaller, error) { + contract, err := bindCCIPCapabilityConfiguration(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationCaller{contract: contract}, nil +} + +func NewCCIPCapabilityConfigurationTransactor(address common.Address, transactor bind.ContractTransactor) (*CCIPCapabilityConfigurationTransactor, error) { + contract, err := bindCCIPCapabilityConfiguration(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationTransactor{contract: contract}, nil +} + +func NewCCIPCapabilityConfigurationFilterer(address common.Address, filterer bind.ContractFilterer) (*CCIPCapabilityConfigurationFilterer, error) { + contract, err := bindCCIPCapabilityConfiguration(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationFilterer{contract: contract}, nil +} + +func bindCCIPCapabilityConfiguration(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CCIPCapabilityConfigurationMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationCaller.contract.Call(opts, result, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationTransactor.contract.Transfer(opts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.CCIPCapabilityConfigurationTransactor.contract.Transact(opts, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPCapabilityConfiguration.Contract.contract.Call(opts, result, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.contract.Transfer(opts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.contract.Transact(opts, method, params...) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getAllChainConfigs") + + if err != nil { + return *new([]CCIPCapabilityConfigurationChainConfigInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPCapabilityConfigurationChainConfigInfo)).(*[]CCIPCapabilityConfigurationChainConfigInfo) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetAllChainConfigs() ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + return _CCIPCapabilityConfiguration.Contract.GetAllChainConfigs(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetAllChainConfigs() ([]CCIPCapabilityConfigurationChainConfigInfo, error) { + return _CCIPCapabilityConfiguration.Contract.GetAllChainConfigs(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getCapabilityConfiguration", arg0) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPCapabilityConfiguration.Contract.GetCapabilityConfiguration(&_CCIPCapabilityConfiguration.CallOpts, arg0) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPCapabilityConfiguration.Contract.GetCapabilityConfiguration(&_CCIPCapabilityConfiguration.CallOpts, arg0) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "getOCRConfig", donId, pluginType) + + if err != nil { + return *new([]CCIPCapabilityConfigurationOCR3ConfigWithMeta), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPCapabilityConfigurationOCR3ConfigWithMeta)).(*[]CCIPCapabilityConfigurationOCR3ConfigWithMeta) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + return _CCIPCapabilityConfiguration.Contract.GetOCRConfig(&_CCIPCapabilityConfiguration.CallOpts, donId, pluginType) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) { + return _CCIPCapabilityConfiguration.Contract.GetOCRConfig(&_CCIPCapabilityConfiguration.CallOpts, donId, pluginType) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.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 (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) Owner() (common.Address, error) { + return _CCIPCapabilityConfiguration.Contract.Owner(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) Owner() (common.Address, error) { + return _CCIPCapabilityConfiguration.Contract.Owner(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CCIPCapabilityConfiguration.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) TypeAndVersion() (string, error) { + return _CCIPCapabilityConfiguration.Contract.TypeAndVersion(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationCallerSession) TypeAndVersion() (string, error) { + return _CCIPCapabilityConfiguration.Contract.TypeAndVersion(&_CCIPCapabilityConfiguration.CallOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "acceptOwnership") +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.AcceptOwnership(&_CCIPCapabilityConfiguration.TransactOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.AcceptOwnership(&_CCIPCapabilityConfiguration.TransactOpts) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "applyChainConfigUpdates", chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.ApplyChainConfigUpdates(&_CCIPCapabilityConfiguration.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.ApplyChainConfigUpdates(&_CCIPCapabilityConfiguration.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "beforeCapabilityConfigSet", arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.BeforeCapabilityConfigSet(&_CCIPCapabilityConfiguration.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.BeforeCapabilityConfigSet(&_CCIPCapabilityConfiguration.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.contract.Transact(opts, "transferOwnership", to) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.TransferOwnership(&_CCIPCapabilityConfiguration.TransactOpts, to) +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPCapabilityConfiguration.Contract.TransferOwnership(&_CCIPCapabilityConfiguration.TransactOpts, to) +} + +type CCIPCapabilityConfigurationCapabilityConfigurationSetIterator struct { + Event *CCIPCapabilityConfigurationCapabilityConfigurationSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationCapabilityConfigurationSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationCapabilityConfigurationSet struct { + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationCapabilityConfigurationSetIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationCapabilityConfigurationSetIterator{contract: _CCIPCapabilityConfiguration.contract, event: "CapabilityConfigurationSet", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationCapabilityConfigurationSet) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseCapabilityConfigurationSet(log types.Log) (*CCIPCapabilityConfigurationCapabilityConfigurationSet, error) { + event := new(CCIPCapabilityConfigurationCapabilityConfigurationSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationChainConfigRemovedIterator struct { + Event *CCIPCapabilityConfigurationChainConfigRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationChainConfigRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationChainConfigRemoved struct { + ChainSelector uint64 + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigRemovedIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationChainConfigRemovedIterator{contract: _CCIPCapabilityConfiguration.contract, event: "ChainConfigRemoved", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigRemoved) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseChainConfigRemoved(log types.Log) (*CCIPCapabilityConfigurationChainConfigRemoved, error) { + event := new(CCIPCapabilityConfigurationChainConfigRemoved) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationChainConfigSetIterator struct { + Event *CCIPCapabilityConfigurationChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationChainConfigSet struct { + ChainSelector uint64 + ChainConfig CCIPCapabilityConfigurationChainConfig + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigSetIterator, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationChainConfigSetIterator{contract: _CCIPCapabilityConfiguration.contract, event: "ChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigSet) (event.Subscription, error) { + + logs, sub, err := _CCIPCapabilityConfiguration.contract.WatchLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPCapabilityConfigurationChainConfigSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseChainConfigSet(log types.Log) (*CCIPCapabilityConfigurationChainConfigSet, error) { + event := new(CCIPCapabilityConfigurationChainConfigSet) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationOwnershipTransferRequestedIterator struct { + Event *CCIPCapabilityConfigurationOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferRequestedIterator, 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 := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationOwnershipTransferRequestedIterator{contract: _CCIPCapabilityConfiguration.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferRequested, 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 := _CCIPCapabilityConfiguration.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(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := _CCIPCapabilityConfiguration.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 (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseOwnershipTransferRequested(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferRequested, error) { + event := new(CCIPCapabilityConfigurationOwnershipTransferRequested) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPCapabilityConfigurationOwnershipTransferredIterator struct { + Event *CCIPCapabilityConfigurationOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CCIPCapabilityConfigurationOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPCapabilityConfigurationOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferredIterator, 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 := _CCIPCapabilityConfiguration.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPCapabilityConfigurationOwnershipTransferredIterator{contract: _CCIPCapabilityConfiguration.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferred, 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 := _CCIPCapabilityConfiguration.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(CCIPCapabilityConfigurationOwnershipTransferred) + if err := _CCIPCapabilityConfiguration.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 (_CCIPCapabilityConfiguration *CCIPCapabilityConfigurationFilterer) ParseOwnershipTransferred(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferred, error) { + event := new(CCIPCapabilityConfigurationOwnershipTransferred) + if err := _CCIPCapabilityConfiguration.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfiguration) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CCIPCapabilityConfiguration.abi.Events["CapabilityConfigurationSet"].ID: + return _CCIPCapabilityConfiguration.ParseCapabilityConfigurationSet(log) + case _CCIPCapabilityConfiguration.abi.Events["ChainConfigRemoved"].ID: + return _CCIPCapabilityConfiguration.ParseChainConfigRemoved(log) + case _CCIPCapabilityConfiguration.abi.Events["ChainConfigSet"].ID: + return _CCIPCapabilityConfiguration.ParseChainConfigSet(log) + case _CCIPCapabilityConfiguration.abi.Events["OwnershipTransferRequested"].ID: + return _CCIPCapabilityConfiguration.ParseOwnershipTransferRequested(log) + case _CCIPCapabilityConfiguration.abi.Events["OwnershipTransferred"].ID: + return _CCIPCapabilityConfiguration.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CCIPCapabilityConfigurationCapabilityConfigurationSet) Topic() common.Hash { + return common.HexToHash("0x84ad7751b744c9e2ee77da1d902b428aec7f0a343d67a24bbe2142e6f58a8d0f") +} + +func (CCIPCapabilityConfigurationChainConfigRemoved) Topic() common.Hash { + return common.HexToHash("0x2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0") +} + +func (CCIPCapabilityConfigurationChainConfigSet) Topic() common.Hash { + return common.HexToHash("0x05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0") +} + +func (CCIPCapabilityConfigurationOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CCIPCapabilityConfigurationOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CCIPCapabilityConfiguration *CCIPCapabilityConfiguration) Address() common.Address { + return _CCIPCapabilityConfiguration.address +} + +type CCIPCapabilityConfigurationInterface interface { + GetAllChainConfigs(opts *bind.CallOpts) ([]CCIPCapabilityConfigurationChainConfigInfo, error) + + GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) + + GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPCapabilityConfigurationOCR3ConfigWithMeta, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPCapabilityConfigurationChainConfigInfo) (*types.Transaction, error) + + BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationCapabilityConfigurationSetIterator, error) + + WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationCapabilityConfigurationSet) (event.Subscription, error) + + ParseCapabilityConfigurationSet(log types.Log) (*CCIPCapabilityConfigurationCapabilityConfigurationSet, error) + + FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigRemovedIterator, error) + + WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigRemoved) (event.Subscription, error) + + ParseChainConfigRemoved(log types.Log) (*CCIPCapabilityConfigurationChainConfigRemoved, error) + + FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPCapabilityConfigurationChainConfigSetIterator, error) + + WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationChainConfigSet) (event.Subscription, error) + + ParseChainConfigSet(log types.Log) (*CCIPCapabilityConfigurationChainConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPCapabilityConfigurationOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPCapabilityConfigurationOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CCIPCapabilityConfigurationOwnershipTransferred, 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 de649f27e2..13aab261a8 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 @@ -5,9 +5,9 @@ burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin fee3f82935ce7a26c65e12f19a472a4fccdae62755abdb42d8b0a01f0f06981a burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin c7efa00d2be62a97a814730c8e13aa70794ebfdd38a9f3b3c11554a5dfd70478 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin a0728e186af74968101135a58a483320ced9ab79b22b1b24ac6994254ee79097 +ccip_capability_configuration: ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.abi ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.bin 75d617a77f82e09a8a4453689fa730a1f369dcf906de750126a3c782b3f885e9 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 -custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 4c7bdddea3decee12887c5bd89648ed3b423bd31eefe586d5cb5c1bc8b883ffe evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin da3b401b00dae39a2851740d00f2ed81d498ad9287b7ab9276f8b10021743d20 diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 2961094925..57a05ae411 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -28,6 +28,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin PriceRegistry price_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.abi ../../../contracts/solc/v0.8.24/CCIPCapabilityConfiguration/CCIPCapabilityConfiguration.bin CCIPCapabilityConfiguration ccip_capability_configuration //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin MaybeRevertMessageReceiver maybe_revert_message_receiver //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin PingPongDemo ping_pong_demo